image.png

解决思路

双指针-滑动窗口

大量的重复计算
即如果我们已经知道nums[i….j]的和,那么就可以很快地知道nums[i….j-1]的和,而不用重复计算
image.png

滑动窗口

image.png

  1. 对于当前的子数组,如果和不到s,则向后多看一个数

image.png
image.png

  1. 看nums[i,….,j+1]的数组的和的大小,如果找到大于s的sum,则记录最小值

image.png

  1. 此时从i端缩小连续子数组,让i—,此时sum就会变小,一直到sum的和小于s

image.png
image.png

  1. 此时j指针继续向前前进,一直到sum的值大于s.依次类推

在整个过程中一直保持一个窗口,该窗口被i和j两个索引所圈定的。该窗口不停地向前滑动来寻找满足题意的数组,即为滑动窗口

  1. public int minSubArrayLen(int s, int[] nums) {
  2. //nums[l,....,r]即为滑动窗口
  3. //初始r为-1即表示最开始滑动窗口中不包含任何元素
  4. int l=0,r=-1;
  5. //res记录最小的连续子数组的长度 这里res初始取nums.length+1表示当前取不到的值
  6. int res = nums.length+1;
  7. //窗口中元素的和
  8. int sum = 0;
  9. //如果l到达了边界 表示没有取值
  10. while(l<nums.length){
  11. //如果sum<s 右边界++ 和累加 此时需要判断数组下标
  12. if(r+1<nums.length && sum<s)
  13. {
  14. //右边界++
  15. r++;
  16. sum += nums[r];
  17. }
  18. //如果sum>=s 和去掉左边界 左边界++
  19. else{
  20. sum -= nums[l];
  21. l++;
  22. }
  23. //如果和大于s 记录res 需要注意【】前闭后闭 应该r-l+1
  24. if(sum>=s){
  25. res = res>r-l+1?r-l+1:res;
  26. }
  27. }
  28. //如果res没有被更新 则没有解
  29. if(res == nums.length+1)
  30. return 0;
  31. return res;
  32. }
  33. //time O(n)
  34. //space O(1)