力扣:长度最小的子数组
代码随想录解析地址
题目:
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
暴力解法代码:
class Solution {
public:
int minSubArrayLen(int s, vector<int>& nums) {
int result = INT32_MAX; // 最终的结果
int sum = 0; // 子序列的数值之和
int subLength = 0; // 子序列的长度
for (int i = 0; i < nums.size(); i++) { // 设置子序列起点为i
sum = 0;
for (int j = i; j < nums.size(); j++) { // 设置子序列终止位置为j
sum += nums[j];
if (sum >= s) { // 一旦发现子序列和超过了s,更新result
subLength = j - i + 1; // 取子序列的长度
result = result < subLength ? result : subLength;
break; // 因为我们是找符合条件最短的子序列,所以一旦符合条件就break
}
}
}
// 如果result没有被赋值的话,就返回0,说明没有符合条件的子序列
return result == INT32_MAX ? 0 : result;
}
};
sum(和)通过sum+=nums [ j ] 来实现,所以for条件是 j = i
for(int j = i; j < nums.size(); j++)
滑动窗口法:
更加快速寻找到最佳范围。
i 指针指向起始位置
j 指针指向终止位置
相比于暴力解法,滑动窗口法的优势解释:
首先 i j 都为0然后移动 j 寻找最佳位置,起始位置为 0 的最佳范围找到了,再寻找起始位置为 1 的最佳范围,和要大于target 此时将 i 指向的位置后移一位(即寻找起始位置为 1 的最佳范围)j 的位置不动,此时的sum就已经可能大于等于target,若 j 指针为此位置的前一位则sum肯定小于target,所以 j 指针就从此位置开始,来判断sum是否大于等于target。(暴力解法是将 j 置于 i 的位置开始寻找最佳范围(麻烦))
**即:**首先锁定i,移动 j 寻找到可用序列,然后锁定 j 移动 i 在这个可用序列中寻找到最短可用序列
通过思考题目来想思路,不要想窗口。
整体思路:
j 不断后移寻找到最适位置,然后进入while对初始化的数据(length,result)进行操作,此时在这个起始位置的最佳范围已经找到,要找下一个位置了,那么此时 i 后移一位,sum更正,此时又进行判断sum是否大于等于target,如果是又进行上面的这个操作,如果不是那么移动 j 找到结束位置。
题目条件:如果不存在符合条件的子数组,返回 0 。
此点通过 result 是否被赋值来判断。
代码:
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int result = INT32_MAX;
int length = 0;
int i = 0;
int sum = 0;
for(int j = 0; j < nums.size(); j++){
sum += nums[j];
while(sum >= target){
length = j - i + 1;
result = result >= length? length:result;
sum -= nums[i++];
}
}
return result == INT32_MAX? 0:result;
}
};
自己解法:
- [ i , j ]构成范围
- 一开始范围是0~ -1表示没有开始
- 范围总和小于目标值
- j出现越界,直接返回
- 没有越界,则加入下一个值
- 范围总和大于目标值
- 是否更新len
- 此时的范围:首元素向后移动一个单位
- 更新sum
class Solution {
public:
int minSubArrayLen(int target, vector<int>& nums) {
int i, j = -1;
i = 0;
int sum = 0;
int len = INT_MAX;
while(i <= nums.size()-1 && j < int(nums.size())){
if(sum < target) {
if(++j == nums.size()) {
if(len == INT_MAX) return 0;
return len;
}
else sum += nums[j];
}
else {
if(len > j-i+1){
len = j-i+1;
}
sum-=nums[i++];
}
}
return len;
}
};
j < int(nums.size()
类型强制转换的原因:j有符号整型,且可能为负值,nums.size()为无符号整型。