1.暴力解法
暴力解法 我的思路是用一个for循环 嵌套一个while循环
然后用q进行计数 看是到达第几个的时候 会大于等于target
时间复杂度是O(n^2);
空间复杂度是O(n);
但是我们会发现在长度很长的数组的时候它会超时。
class Solution {
public int minSubArrayLen(int target, int[] nums){
int h = 0;
for(int i = 0;i<nums.length;i++)
{
h+=nums[i];
}
if(h<target) return 0;//特殊情况就是全加上了还是太小 所以我们就需要直接return 0
int min = Integer.MAX_VALUE;
for(int i = 0;i<nums.length;i++)
{
int q = 1;//计数
int n = nums[i];//从第几个开始
int m = i+1;//从后面一个开始相加
while(m<nums.length&&n<target)
{
n = n+ nums[m];
m++;
q++;
}//当超过或达到最后一个的时候就跳出循环
if(q<=min&&n>=target) min = q;
//要不然比如一个数组 他全部加起来是有超过Target的 但是当m变成最后一个的时候 也会跳出那个循环
//并且此时q为1 那么会导致最后的结果不准确
}
return min;
}
}
2.滑动窗口
滑动窗口的精髓在于 用暴力解法的话 就是一遍一遍for循环 推倒重来
但是滑动窗口可以保证 因为起始位置和末尾位置都在改变 所以保证了说效率比较高
原理如下
class Solution {
// 滑动窗口
public int minSubArrayLen(int s, int[] nums) {
int left = 0;
int sum = 0;
int result = Integer.MAX_VALUE;
for (int right = 0; right < nums.length; right++) {
//为什么right是末尾位置呢 因为我们需要知道 如果是left写在里
//是不是就和暴力一样一遍一遍for循环推倒重来
sum+=nums[right];
while(sum>=s)//那么为什么要用where呢 是因为比如s是一百 现在是1,1,1,1,1...105
//那么加到最后一个就是106 如果是用if 那么--一个之后 仍然是105 仍然大于 但是我们起始位置要跑到
//下一次让它小于的地方所以用where
{
result = Math.min(result, right - left + 1);
sum -= nums[left++];//这里就是滑动窗口的精髓 起始位置的移动就是在这里移动
}
}
return result == Integer.MAX_VALUE ? 0 : result;
}
}
}
这样时间复杂度就变成了O(n)