2.1.3. Cumulative Sum
Sometimes, we also call cumulative sum as prefix sum, or left sum.
In C++, to cumulative sum, we can use partial_sum
:
[cling]$ #include <sein.hpp>
[cling]$ vector<int> v={1,2,3,4};
[cling]$ partial_sum(v.begin(), v.end(), v.begin());
[cling]$ v
(std::vector<int> &) { 1, 3, 6, 10 }
2.1.3.1. Maximum Size Subarray Sum Equals k
Given an integer array nums and an integer k, return the maximum length of a subarray that sums to k. If there is not one, return 0 instead.
1int max_length_sum_k(vector<int>& nums, int k) {
2 int csum = 0, r = 0;
3 unordered_map<int, int> m; // cumulative sum to index
4 for (int i = 0; i < nums.size(); ++i) {
5 csum += nums[i];
6 if (csum == k)
7 r = i + 1;
8 else if (m.count(csum - k))
9 r = max(r, i - m[csum - k]);
10 if (!m.count(csum)) m[csum] = i;
11 }
12 return r;
13}
2.1.3.2. Longest Subarray With Equal 0 and 1
Given a binary array, find the maximum length of a subarray with equal number of 0 and 1.
The O(N) solution to this problem is very clever. Replace all 0s with -1, and then use the Maximum Size Subarray Sum Equals k method (2sum) to solve, where k is 0.
1int max_length_equal01(vector<int>& n) { // TC: O(N), SC: O(1)
2 transform(n.begin(), n.end(), n.begin(), [](int i) { return i ? i : -1; });
3 map<int, int> m; // cumulative sum to index
4 int csum = 0, r = 0;
5 for (int i = 0; i < n.size(); ++i) {
6 csum += n[i];
7 if (csum == 0)
8 r = i + 1;
9 else if (m.count(csum))
10 r = max(r, i - m[csum]);
11 else
12 m[csum] = i;
13 }
14 return r;
15}
2.1.3.3. Continuous Subarray Sum
Given a list of non-negative numbers and a target integer k, write a function to check if the array has a continuous subarray of size at least 2 that sums up to the multiple of k, that is, sums up to n*k where n is also an integer.
It is easy to prove that if the numbers a and b are divided by the number c, if the remainders are the same, then (a-b) must be able to divide c. According to this, the problem can be solved in O(N).
There are two troubles in this question: 1, the length of the subarray must be greater than or equal to 2; 2, if k is 0, there will be an edge case, and the logic will be different.
1bool check_subarray_sum(vector<int>& n, int k) {
2 if (n.size() < 2) return 0;
3 if (k == 0) {
4 for (int i = 0; i < n.size() - 1; ++i)
5 if (n[i] == 0) return n[i + 1] == 0;
6 return 0;
7 }
8 partial_sum(n.begin(), n.end(), n.begin());
9 unordered_set<int> s = {n[0] % k};
10 for (int i = 1; i < n.size(); ++i) {
11 if (n[i] % k == 0 or s.count(n[i] % k)) return 1;
12 s.insert(n[i] % k);
13 }
14 return 0;
15}
2.1.3.4. Maximum Subarray
Find the contiguous subarray within an array (containing at least one number) which has the largest sum.
For example, given the array [-2,1,-3,4,-1,2,1,-5,4], the contiguous subarray [4,-1,2,1] has the largest sum = 6.
1int max_sum_subarray(vector<int>& nums) {
2 int mx = *max_element(nums.begin(), nums.end()); // all negative case
3 partial_sum(nums.begin(), nums.end(), nums.begin()); // cum sum
4 int mi = nums[0], r = mi;
5 for (int i = 1; i < nums.size(); ++i)
6 r = max(r, nums[i] - mi), mi = min(mi, nums[i]);
7 return max(max(mx, r), *max_element(nums.begin(), nums.end()));
8}
👽 Find the index of the corresponding start and end.