LeetCode 209. Minimum Size Subarray Sum
Given an array of positive integers nums and a positive integer target, return the minimal length of a contiguous subarray [numsl, numsl+1, ..., numsr-1, numsr]
of which the sum is greater than or equal to target. If there is no such subarray, return 0 instead.
Example 1:
cpp
Input: target = 7, nums = [2,3,1,2,4,3]
Output: 2
Explanation: The subarray [4,3] has the minimal length under the problem constraint.
Example 2:
cpp
Input: target = 4, nums = [1,4,4]
Output: 1
method: 滑动窗口
sum
是区间[j, i]
的和
- 如果
sum
小于target
,区间就扩大,即i++
- 如果
sum
大于target
,区间就缩小,即j++
cpp
int minSubArrayLen(int target, vector<int>& nums) {
int res = INT_MAX;
int sum = 0;
for (int i = 0, j = 0; i < nums.size(); i++) {
sum += nums[i]; // 就硬加
while (sum >= target) { // 大于等于target就记录结果
res = min(res, i - j + 1); // [j, i]
sum -= nums[j];
j++; // j移动,区间缩小
}
}
return res == INT_MAX ? 0 : res;
}
时间复杂度:O(n)
LeetCode 862. 和至少为 K 的最短子数组
给你一个整数数组 nums
和一个整数 k
,找出 nums
中和至少为 k
的 最短非空子数组 ,并返回该子数组的长度。如果不存在这样的 子数组 ,返回 -1 。
子数组 是数组中 连续 的一部分。
示例 1:
cpp
输入:nums = [2,-1,2], k = 3
输出:3
method: 前缀和+单调双端队列
prefix[i]
记录的是0
到i-1
的前缀和
对于一个prefix[y],我们希望找到一个prefix[x],使得prefix[y]−prefix[x]≥k,并且使得y−x最小
- 队列里面的前缀和是单调递增的(虽然存的是下标),如果prefix[y]比队列末尾的元素小,队列的末尾元素就要弹出,因为如果x1<x2,且prefix[x1]≥prefix[x2],此时x1满足prefix[y]−prefix[x1]≥k,那么x2肯定也满足prefix[y]−prefix[x2]≥k,因为prefix[x2]更小,并且x2更大,所以y−x2肯定小于y−x1,所以肯定要取x2,不会取x1,所以直接弹出
- 因为是递增的,所以来一个prefix[y],就从队头开始找是否有prefix[x],使得prefix[y]−prefix[x]≥k成立,如果第一个就不成立,后面肯定都不成立,所以不用找了,如果第一个成立,后面可能还有成立的,所以要继续找,所以用
while
,并且要将成立的prefix[x]弹出,因为即使后面又来了一个prefix[y′],y−x肯定小于y′−x,所以直接弹出
cpp
int shortestSubarray(vector<int>& nums, int k) {
int n = nums.size();
vector<long> prefix(n + 1);
for (int i = 1; i <= n; i++) {
prefix[i] = prefix[i - 1] + nums[i - 1];
}
deque<int> dq;
dq.push_back(0);
int res = INT_MAX;
for (int i = 1; i <= n; i++) {
while (!dq.empty() && prefix[i] <= prefix[dq.back()]) {
dq.pop_back();
}
while (!dq.empty() && prefix[i] - prefix[dq.front()] >= k) {
res = min(res, i - dq.front()); // 找到了就更新结果 [dq.front(), i)
dq.pop_front(); // 然后将队头元素弹出
}
dq.push_back(i); // 队列里存的是下标
}
return res == INT_MAX ? -1 : res;
}