推荐阅读
从零开始学数组:深入浅出,带你掌握核心要点
初探二分法
再探二分法
目录
- 推荐阅读
- 209.长度最小的子数组
- 题目
- 思路
- 解法
- 暴力解法
- 队列相加法(滑动窗口)
- 对列相减法(滑动窗口)
系统的纪录一下刷算法的过程,之前一直断断续续的刷题,半途而废,现在重新开始。话不多说,开冲!
209.长度最小的子数组
题目
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其总和大于等于 target的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。
思路
暴力解法主要就是两个for循环,一个for循环固定一个数组元素,例如n,另一个for循环从n的下一个元素开始累加,当和大于等于target时终止内层循环,并记录该最小长度。
滑动窗口(其实可以看成队列)主要就是通过不断地调节子序列的起始位置和终止位置来得到相应的结果。
我们把数组中的元素不停的入队,直到总和大于等于 s 为止,接着记录下队列中元素的个数,然后再不停的出队,直到队列中元素的和小于 s 为止(如果不小于 s,也要记录下队列中元素的个数,这个个数其实就是不小于 s 的连续子数组长度,我们要记录最小的即可)。接着再把数组中的元素添加到队列中……重复上面的操作,直到数组中的元素全部使用完为止。
解法
暴力解法
代码示例:
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int result = Integer.MAX_VALUE;
for (int i = 0; i < nums.length; i++) {
int sum = 0;
for (int j = i; j < nums.length; j++) {
sum += nums[j];
if (sum >= target) {
result = Math.min(result, j - i + 1);
break;
}
}
}
return result == Integer.MAX_VALUE ? 0 : result;
}
}
- 时间复杂度:O(n^2)
- 空间复杂度:O(1)
队列相加法(滑动窗口)
代码示例
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int result = Integer.MAX_VALUE;
int startIndex=0;
int endIndex=0;
int sum = 0;
for (endIndex=0; endIndex < nums.length; endIndex++) {
sum+=nums[endIndex];
while (sum>=target) {
result=Math.min(result,endIndex-startIndex+1);
sum-=nums[startIndex];
startIndex++;
}
}
return result == Integer.MAX_VALUE ? 0 : result;
}
}
- 时间复杂度:O(n)
- 空间复杂度:O(1)
对列相减法(滑动窗口)
代码示例
class Solution {
public int minSubArrayLen(int target, int[] nums) {
int result = Integer.MAX_VALUE;
int startIndex=0;
int endIndex=0;
int sum = 0;
for (endIndex=0; endIndex < nums.length; endIndex++) {
target-=nums[endIndex];
while (target<=0) {
result=Math.min(result,endIndex-startIndex+1);
target+=nums[startIndex];
startIndex++;
}
}
return result == Integer.MAX_VALUE ? 0 : result;
}
}
- 时间复杂度:O(n)
- 空间复杂度:O(1)