2022.10.26每日打卡
题目
给你一个整数数组 nums 和一个整数 k ,找出 nums 中和至少为 k 的 最短非空子数组 ,并返回该子数组的长度。如果不存在这样的 子数组 ,返回 -1 。
子数组 是数组中 连续 的一部分。
示例 1:
输入:nums = [1], k = 1
输出:1
示例 2:
输入:nums = [1,2], k = 4
输出:-1
示例 3:
输入:nums = [2,-1,2], k = 3
输出:3
提示:
1 <= nums.length <= 105
-105 <= nums[i] <= 105
1 <= k <= 109
标准代码
class Solution {
public:
int shortestSubarray(vector<int> &nums, int k) {
int n = nums.size(), ans = n + 1;
long s[n + 1];
s[0] = 0L;
for (int i = 0; i < n; ++i)
s[i + 1] = s[i] + nums[i]; // 计算前缀和
deque<int> q;
for (int i = 0; i <= n; ++i) {
long cur_s = s[i];
while (!q.empty() && cur_s - s[q.front()] >= k) {
ans = min(ans, i - q.front());
q.pop_front(); // 优化一
}
while (!q.empty() && s[q.back()] >= cur_s)
q.pop_back(); // 优化二
q.push_back(i);
}
return ans > n ? -1 : ans;
}
};
解题思路
本题求最短满足要求的子序列的长度,可以转化为前缀和问题,创建一个双端队列存储前缀,当队尾减队首的值大于k时,代表此时已经满足要求,且随后的最短子序列计算中已经不可能在包括队首元素,故将队首出队,更新最短长度,当入队新元素时,若入队元素小于队尾元素,则说明若队尾元素能满足大于k的要求,则新入队元素也一定能满足,所以出队队尾元素,将新元素入队。处理完全部的前缀和后,更新到最后的最短长度即为所求。