Add subarray sum equals K flashcards (LC 560, 974, 325)
This commit is contained in:
@@ -81,3 +81,19 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
#+end_src
|
#+end_src
|
||||||
|
|
||||||
|
|
||||||
|
* TODO study: why min doesn't work with Fenwick tree (no inverse, update breaks on increase)
|
||||||
|
|
||||||
|
* Binary search
|
||||||
|
#+begin_src python
|
||||||
|
def bs(a, x, l, r):
|
||||||
|
if l >= r:
|
||||||
|
return l
|
||||||
|
|
||||||
|
m = l + (r-l) // 2
|
||||||
|
if (a[m] < x):
|
||||||
|
return bs(a, x, m+1, r);
|
||||||
|
else:
|
||||||
|
return bs(a, x, l, m)
|
||||||
|
#+end_src
|
||||||
|
|||||||
@@ -0,0 +1,167 @@
|
|||||||
|
#+title: Subarrays with Sum Equal to K
|
||||||
|
* Subarray Sum Equals K - Brute Force [algorithm:array]
|
||||||
|
:PROPERTIES:
|
||||||
|
:ANKI_NOTE_TYPE: Basic
|
||||||
|
:LINK: https://leetcode.com/problems/subarray-sum-equals-k/description/
|
||||||
|
:END:
|
||||||
|
** Front
|
||||||
|
Find the total number of continuous subarrays whose sum equals k. Solve using the brute force approach.
|
||||||
|
Example: nums = [1,2,3], k = 3 → Output: 2 ([1,2] and [3])
|
||||||
|
|
||||||
|
** Back
|
||||||
|
#+begin_src c++
|
||||||
|
int subarraySum(vector<int>& nums, int k) {
|
||||||
|
int count = 0;
|
||||||
|
for (int i = 0; i < nums.size(); i++) {
|
||||||
|
int sum = 0;
|
||||||
|
for (int j = i; j < nums.size(); j++) {
|
||||||
|
sum += nums[j];
|
||||||
|
if (sum == k) count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
#+end_src
|
||||||
|
Time: O(n^2), Space: O(1)
|
||||||
|
|
||||||
|
* Subarray Sum Equals K - Prefix Sum + Hash Map [algorithm:array]
|
||||||
|
:PROPERTIES:
|
||||||
|
:ANKI_NOTE_TYPE: Basic
|
||||||
|
:LINK: https://leetcode.com/problems/subarray-sum-equals-k/description/
|
||||||
|
:END:
|
||||||
|
** Front
|
||||||
|
Find the total number of continuous subarrays whose sum equals k. Solve optimally using prefix sum with a hash map.
|
||||||
|
Example: nums = [1,2,3], k = 3 → Output: 2
|
||||||
|
|
||||||
|
** Back
|
||||||
|
#+begin_src c++
|
||||||
|
int subarraySum(vector<int>& nums, int k) {
|
||||||
|
unordered_map<int,int> prefixCount;
|
||||||
|
prefixCount[0] = 1; // base case: sum of 0 appears once
|
||||||
|
int sum = 0, count = 0;
|
||||||
|
for (int num : nums) {
|
||||||
|
sum += num;
|
||||||
|
// If (sum - k) exists, those prefixes form valid subarrays
|
||||||
|
count += prefixCount[sum - k];
|
||||||
|
prefixCount[sum]++;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
#+end_src
|
||||||
|
Time: O(n), Space: O(n)
|
||||||
|
|
||||||
|
* Subarray Sum Equals K - Why prefixCount[0] = 1 [algorithm:interview]
|
||||||
|
:PROPERTIES:
|
||||||
|
:ANKI_NOTE_TYPE: Basic
|
||||||
|
:LINK: https://leetcode.com/problems/subarray-sum-equals-k/description/
|
||||||
|
:END:
|
||||||
|
** Front
|
||||||
|
In the optimal subarray sum solution (prefix sum + hash map), why is `prefixCount[0] = 1` initialized?
|
||||||
|
|
||||||
|
** Back
|
||||||
|
It handles the case where a subarray starts from index 0 and its sum equals k.
|
||||||
|
|
||||||
|
When sum == k at some index, we look up prefixCount[sum - k] = prefixCount[0].
|
||||||
|
Without the initialization, this lookup would return 0, missing valid subarrays like [3] where k = 3.
|
||||||
|
|
||||||
|
The base case means: "a prefix sum of 0 exists once (before any element)" — conceptually the empty prefix.
|
||||||
|
|
||||||
|
* Subarray Sum Divisible by K [algorithm:array]
|
||||||
|
:PROPERTIES:
|
||||||
|
:ANKI_NOTE_TYPE: Basic
|
||||||
|
:LINK: https://leetcode.com/problems/subarray-sums-divisible-by-k/description/
|
||||||
|
:END:
|
||||||
|
** Front
|
||||||
|
Find the total number of continuous subarrays whose sum is divisible by k.
|
||||||
|
Example: nums = [23,2,4,6,7], k = 6 → Output: 2 ([2,4] and [7])
|
||||||
|
|
||||||
|
** Back
|
||||||
|
#+begin_src c++
|
||||||
|
int subarraysDivByK(vector<int>& nums, int k) {
|
||||||
|
unordered_map<int,int> prefixCount;
|
||||||
|
prefixCount[0] = 1;
|
||||||
|
int sum = 0, count = 0;
|
||||||
|
for (int num : nums) {
|
||||||
|
sum += num;
|
||||||
|
// Modulo can be negative in C++, fix with ((sum % k) + k) % k
|
||||||
|
int remainder = ((sum % k) + k) % k;
|
||||||
|
count += prefixCount[remainder];
|
||||||
|
prefixCount[remainder]++;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
#+end_src
|
||||||
|
Key insight: If two prefix sums have the same remainder mod k, their subarray sum is divisible by k.
|
||||||
|
|
||||||
|
Time: O(n), Space: O(min(n, k))
|
||||||
|
|
||||||
|
* Longest Subarray Sum Equals K [algorithm:array]
|
||||||
|
:PROPERTIES:
|
||||||
|
:ANKI_NOTE_TYPE: Basic
|
||||||
|
:LINK: https://leetcode.com/problems/maximum-size-subarray-sum-equals-k/description/
|
||||||
|
:END:
|
||||||
|
** Front
|
||||||
|
Find the maximum length of a contiguous subarray that sums to k.
|
||||||
|
Example: nums = [1,-1,5,-2,3], k = 3 → Output: 4 ([1,-1,5,-2])
|
||||||
|
|
||||||
|
** Back
|
||||||
|
#+begin_src c++
|
||||||
|
int maxSubArrayLen(vector<int>& nums, int k) {
|
||||||
|
unordered_map<int,int> firstOccurrence;
|
||||||
|
firstOccurrence[0] = 0; // sum 0 at index 0 (1-based)
|
||||||
|
int sum = 0, maxLen = 0;
|
||||||
|
for (int i = 0; i < nums.size(); i++) {
|
||||||
|
sum += nums[i];
|
||||||
|
// Check if subarray ending here sums to k
|
||||||
|
if (firstOccurrence.count(sum - k)) {
|
||||||
|
maxLen = max(maxLen, i + 1 - firstOccurrence[sum - k]);
|
||||||
|
}
|
||||||
|
// Store first occurrence only (for longest)
|
||||||
|
if (!firstOccurrence.count(sum)) {
|
||||||
|
firstOccurrence[sum] = i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return maxLen;
|
||||||
|
}
|
||||||
|
#+end_src
|
||||||
|
Key difference from counting: store only the *first* occurrence of each prefix sum to maximize length.
|
||||||
|
|
||||||
|
Time: O(n), Space: O(n)
|
||||||
|
|
||||||
|
* Subarray Sum Equals K - Negative Numbers? [algorithm:interview]
|
||||||
|
:PROPERTIES:
|
||||||
|
:ANKI_NOTE_TYPE: Basic
|
||||||
|
:LINK: https://leetcode.com/problems/subarray-sum-equals-k/description/
|
||||||
|
:END:
|
||||||
|
** Front
|
||||||
|
Does the prefix sum + hash map approach for "subarray sum equals k" work when the array contains negative numbers? Why?
|
||||||
|
|
||||||
|
** Back
|
||||||
|
Yes, it works with negative numbers.
|
||||||
|
|
||||||
|
The prefix sum approach does NOT require positive-only elements. It works for any integer array because:
|
||||||
|
- prefix[j] - prefix[i] = sum[i+1..j] is always true regardless of sign
|
||||||
|
- The hash map tracks ALL prefix sums seen, positive or negative
|
||||||
|
- We only need (sum - k) to exist in the map
|
||||||
|
|
||||||
|
This makes it superior to the sliding window approach, which only works for non-negative arrays.
|
||||||
|
|
||||||
|
* Subarray Sum Equals K - Sliding Window Limitation [algorithm:interview]
|
||||||
|
:PROPERTIES:
|
||||||
|
:ANKI_NOTE_TYPE: Basic
|
||||||
|
:LINK: https://leetcode.com/problems/subarray-sum-equals-k/description/
|
||||||
|
:END:
|
||||||
|
** Front
|
||||||
|
Can you use the sliding window technique to solve "subarray sum equals k"? When does it work?
|
||||||
|
|
||||||
|
** Back
|
||||||
|
Sliding window ONLY works when all elements are non-negative (positive or zero).
|
||||||
|
|
||||||
|
When all elements >= 0:
|
||||||
|
- Expanding the window increases the sum
|
||||||
|
- Shrinking the window decreases the sum
|
||||||
|
- This monotonicity lets us adjust the window
|
||||||
|
|
||||||
|
Sliding window fails with negative numbers because adding/removing elements doesn't monotonically change the sum.
|
||||||
|
|
||||||
|
Prefer prefix sum + hash map — it works for all cases (positive, negative, zero).
|
||||||
Reference in New Issue
Block a user