Given an integer array nums and an integer k, return the length of the shortest non-empty subarray of nums with a sum of at least k. If there is no such subarray, return -1.
A subarray is a contiguous part of an array.
Example 1
Input: nums = [1], k = 1
Output: 1
Example 2
Input: nums = [1,2], k = 4
Output: -1
Example 3
Input: nums = [2,-1,2], k = 3
Output: 3
Constraints
- 1 <= nums.length <= 1e5
- -1e5 <= nums[i] <= 1e5
- 1 <= k <= 1e9
Solution
超时的暴力:
class Solution {
public:
int shortestSubarray(vector<int>& nums, int k) {
for (int i = 1; i <= nums.size(); i++) {
for (int j = 0; j < nums.size(); j++) {
int sum = 0;
for (int l = j; j + i <= nums.size() && l < j + i; l++) {
sum += nums[l];
}
if (sum >= k) return i;
}
}
return -1;
}
};
加上前缀和数组优化后还是超时:(求区间元素和以后要想到前缀和优化了)
class Solution {
public:
int shortestSubarray(vector<int>& nums, int k) {
vector<int> presum(nums.size());
presum[0] = nums[0];
for (int i = 1; i < nums.size(); i++) {
presum[i] = presum[i - 1] + nums[i];
}
for (int i = 1; i <= nums.size(); i++) {
for (int j = 0; j + i - 1 < nums.size(); j++) {
if (presum[j + i - 1] - presum[j] + nums[j] >= k) return i;
}
}
return -1;
}
};
前缀和 + 单调双端队列:
class Solution {
public:
int shortestSubarray(vector<int>& nums, int k) {
int n = nums.size();
vector<long> presum(n + 1); //前缀和可能会溢出
//生成前缀和数组
presum[0] = 0;
for (int i = 0; i < n; i++) presum[i + 1] = presum[i] + nums[i];
//遍历前缀和数组
deque<int> q;
int ans = INT_MAX;
for (int i = 0; i <= n; i++) {
//判队首
while (!q.empty() && presum[i] - presum[q.front()] >= k) {
ans = min(ans, i - q.front());
q.pop_front();
}
//判队尾
while (!q.empty() && presum[q.back()] >= presum[i]) {
q.pop_back();
}
//遍历入队
q.push_back(i);
}
if (ans == INT_MAX) ans = -1;
return ans;
}
};