题目:
给定一个含有 n
个正整数的数组和一个正整数 target
。
找出该数组中满足其总和大于等于 target
的长度最小的 连续子数组
[numsl, numsl+1, ..., numsr-1, numsr]
,并返回其长度。如果不存在符合条件的子数组,返回 0
。
示例 1:
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3]
是该条件下的长度最小的子数组。
示例 2:
输入:target = 4, nums = [1,4,4] 输出:1
示例 3:
输入:target = 11, nums = [1,1,1,1,1,1,1,1] 输出:0
提示:
1 <= target <= 109
1 <= nums.length <= 105
1 <= nums[i] <= 105
进阶:
- 如果你已经实现
O(n)
时间复杂度的解法, 请尝试设计一个O(n log(n))
时间复杂度的解法。
思路:
暴力破解,定义嵌套循环,暴力破解实现解题。
通过两个for循环的嵌套,不断移动起点查询满足条件的最短子序列。
解题过程:
获取数组长度。
int length = nums.size();
定义输出变量sublen,子数组长度,因为需要不断找最小长度,初始声明时将长度设置为INT32_MAX,以此不断更新长度。
int sublen = INT32_MAX;
定义变量sum,目的是不断累加,当超过target的值时,则此段为一个子数组。
int sum = 0;
定义暴力破解的嵌套for循环。外层循环从0开始,内层循环从i开始,寻找从i开始的每个符合长度的子数组。
for(int i = 0; i < length; i++){
for(int j = i ;j < length; j++){
}
}
继续完善循环体内容。在外循环开始时需要重置sum。内循环对sum不断累加直到达到目标值或溢出右边界。
for(int i = 0; i < length; i++){
sum = 0;
for(int j = i ;j < length; j++){
sum += nums[j];
if(sum >= target){
sublen = min(sublen, j - i + 1);
break;
}
}
}
返回sublen,如果没找到符合的子数组,则sublen没被更新,返回0。
return sublen == INT32_MAX ? 0 : sublen;
题解:
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int length = nums.size();
int sublen = INT32_MAX;
int sum = 0;
for(int i = 0; i < length; i++){
sum = 0;
for(int j = i ;j < length; j++){
sum += nums[j];
if(sum >= target){
sublen = min(sublen, j - i + 1);
break;
}
}
}
return sublen == INT32_MAX ? 0 : sublen;
}
};
leetcode的测试用例超时了。考虑另一种方法。
思路:
由于暴力破解超时,考虑使用滑动窗口法,也是一种双指针法,左指针指向起点,右指针向右遍历,不断累加直到大于等于目标值。
储存此时的长度。
sum减掉左指针指向值,将左指针右移一位,继续移动右指针,直到满足条件。
判断长度是否小于之前的长度,更新长度。
解题过程:
获取数组长度。
int length = nums.size();
定义输出变量sublen,子数组长度,因为需要不断找最小长度,初始声明时将长度设置为INT32_MAX,以此不断更新长度。
int sublen = INT32_MAX;
定义变量sum,目的是不断累加,当超过target的值时,则此段为一个子数组。
int sum = 0;
定义左指针
int left = 0;
定义循环体。循环只移动右指针向前探索并不断累加,当探索到边界则退出循环。
for(int right = 0; right < length; right++){
sum += nums[right];
}
当sum值超过target时,储存此时的子数组长度,减去左指针指向值,并将左指针右移一位。也就是将窗口向右滑动。
while(sum >= target){
sublen = min(sublen, right - left + 1);
sum -= nums[left];
left++;
}
组合循环体内容。
for(int right = 0; right < length; right++){
sum += nums[right];
while(sum >= target){
sublen = min(sublen, right - left + 1);
sum -= nums[left];
left++;
}
}
返回sublen,如果没找到符合的子数组,则sublen没被更新,返回0。
return sublen == INT32_MAX ? 0 : sublen;
题解:
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int length = nums.size();
int sublen = INT32_MAX;
int left = 0;
int sum = 0;
for(int right = 0; right < length; right++){
sum += nums[right];
while(sum >= target){
sublen = min(sublen, right - left + 1);
sum -= nums[left];
left++;
}
}
return sublen == INT32_MAX ? 0 : sublen;
}
};