continuous subarray
一、连续数组的和
1.等于target ( LC 560)
1)题目
Given an array of integers nums and an integer k, return the total number of continuous subarrays whose sum equals to k.
(连续array,有负数,等于某个target)
2)思路
前缀和:a[i]+…+a[j] = s[I] - s[j - 1] = k
遍历每一个数,检查s[i] - k是否存在于之前的前缀和set中,如果存在说明存在 s[I] - s[j - 1] = k; 并且同时存储当前的前缀和。
3)题解
int subarraySum(vector<int>& nums, int k) {
unordered_map<int, int> hash;
int sum = 0;
int res = 0;
hash[0]++;
for (int i = 0; i < nums.size(); i++) {
sum += nums[i];
res += hash[sum - k];
hash[sum]++;
}
return res;
}
2.连续和等于target的倍数(LC 523)
1)题目
Given an integer array nums and an integer k, return true if nums has a continuous subarray of size at least two whose elements sum up to a multiple of k, or false otherwise.
An integer x is a multiple of k if there exists an integer n such that x = n * k. 0 is always a multiple of k.
连续array(长度至少为2), 非负数, 等于target的倍数
2)思路
- 前缀和:我们不关心前缀和的实际大小,只关心他除以target的余数是不是0–只关心每个数除以k的余数,如果两个前缀和除以k的余数相同,那么他们的差除以k的余数为0.
- 长度至少为2:插入i-2的数
3)题解
bool checkSubarraySum(vector<int>& nums, int k) {
int s[nums.size() + 1];
s[0] = 0;
for (int i = 1; i <= nums.size(); i++) s[i] = s[i - 1] + nums[i - 1];
unordered_set<int> hash;
for (int i = 2; i <= nums.size(); i++) {
hash.insert(s[i - 2] % k);
if (hash.count(s[i] % k)) return true;
}
return false;
}
3.连续和能够整除k(LC 974)
1)题目
Given an integer array nums and an integer k, return the number of non-empty subarrays that have a sum divisible by k.
A subarray is a contiguous part of an array.
连续array(长度最短为1), 有负数, 等于target的倍数
2)思路
- 前缀和:我们不关心前缀和的实际大小,只关心他除以target的余数是不是0–只关心每个数除以k的余数,如果两个前缀和除以k的余数相同,那么他们的差除以k的余数为0.
- 负数处理:(s[i]%k+k)%k (一个负数的余数为-1,另一个正数的余数为k-1,这两个数的差是能被k整除的,应该把他们分到一组。
3)题解
int subarraysDivByK(vector<int>& nums, int k) {
int res = 0;
int s[nums.size() + 1];
s[0] = 0;
for (int i = 1; i <= nums.size(); i++) {
s[i] = s[i - 1] + nums[i - 1];
s[i] = (s[i] % k + k) % k;
}
unordered_map<int, int> hash;
for (int i = 1; i <= nums.size(); i++) {
hash[s[i - 1]]++;
if (hash.count(s[i])) res += hash[s[i]];
}
return res;
}
4.最大subarray和(LC 53)
1)题目
Given an integer array nums, find the contiguous subarray (containing at least one number) which has the largest sum and return its sum.
A subarray is a contiguous part of an array.
连续array(长度最短为1), 有负数, 求最大和
2)思路
DP:dp[i] = max(dp[i-1]+nums[i], ,nums[i])
可以优化空间到O(1)
3)题解
int maxSubArray(vector<int>& nums) {
int m = -1e5;
int res = -1e5;
for (int i = 0; i < nums.size(); i++) {
m = max(m + nums[i], nums[i]);
res = max(m, res);
}
return res;
}
二、连续数组的乘积
1.小于target ( LC 713)
1)题目
Given an array of integers nums and an integer k, return the number of contiguous subarrays where the product of all the elements in the subarray is strictly less than k.
(连续array,正数,小于某个target)
2)思路
双指针,第二个指针每次向后移动一位,如果区间内乘积小于target,则让结果加上此窗口的长度,否则移动第一个指针,使得区间的乘积小于target。
3)题解
int numSubarrayProductLessThanK(vector<int>& nums, int k) {
int cur = 1;
int res = 0;
for (int i = 0, j = 0; j < nums.size(); j++) {
cur *= nums[j];
while(i < j && cur >= k) {
cur /= nums[i];
i++;
}
if(cur < k) res += (j - i + 1);
}
return res;
}
2.最大连续乘积 ( LC 152)
1)题目
Given an integer array nums, find a contiguous non-empty subarray within the array that has the largest product, and return the product.
It is guaranteed that the answer will fit in a 32-bit integer.
A subarray is a contiguous subsequence of the array.
2)思路
记录当前最大的正数和最大的负数
3)题解
int maxProduct(vector<int>& nums) {
int n = nums.size();
int f = 1, g = 1;
int res = INT_MIN;
for (int i = 0; i < n; i++) {
int temp1 = f * nums[i];
int temp2 = g * nums[i];
f = max(nums[i], max(temp1, temp2));
g = min(nums[i], min(temp1, temp2));
res = max(res, f);
}
return res;
}