时间复杂度:O(n2) 空间复杂度:O(1)
使用两层for循环来解答,第一层i
表示起始位置,第二层j
表示结束位置
起始从0开始不断右移,结束位置从i
开始向后一直累加,直到和>=目标值,此时是以i开头得到的最小长度,那么当前这个初始位置最小长度已拿到,break跳出
var minSubArrayLen = function (target, nums) {
let result = Infinity; // 初始化无限大值
let len = nums.length;
for (let i = 0; i < len; i++) {
let sum = 0;
for (let j = i; j < len; j++) {
sum = sum + nums[j];
if (sum >= target) {
result = Math.min(result, j - i + 1);
// 已经获取到以i开头的最小长度,跳出本次循环
break;
}
}
}
return result === Infinity ? 0 : result;
};
但是好像暴力解答会无法通过leetcode,提示超出时间限制,所以还是选择下一种方法:利用滑动窗口来解决更好,这可以让时间复杂度降低为O(n)
时间复杂度:O(n) 空间复杂度:O(1)
利用滑动窗口来解决问题,循环的时候**i
**表示结束位置,计算前n项和,如果前n项和>=target,那么移动slow(起始位置)指针,缩小窗口范围,保证当前窗口范围是达到目标的最小长度数组
滑动窗口在双层for循环的基础上减少为一次循环,之所以可以这样做是因为初始位置是可以不用往回走的,也就是说只要查找到了合适的数组范围,那么slow只需要向前移动,不需要回退,因为缩小到了最小范围以后我们会让i++,这时候范围扩大,就把满足条件的范围也扩大,此时从上次截止的slow开始算起,也是满足范围的,不需要slow在从0开始向前走
图片来自代码随想录
var minSubArrayLen = function (target, nums) {
let sum = 0; // 记录总和
let result = Infinity; // 记录最小连续数组长度
let slow = 0; // 起始指针
for(let i = 0;i<nums.length;i++){
sum = sum + nums[i];
while(sum >= target){
result = Math.min(result,i - slow + 1);
// 移动起始指针
sum = sum - nums[slow];
slow++
}
}
return result === Infinity ? 0 : result;
};