这么简单的滑动窗口都不会,这么久的算法白学了

77 阅读2分钟

“我报名参加金石计划1期挑战——瓜分10万奖池,这是我的第1篇文章,点击查看活动详情

题目描述

image.png

题目分析

粗略一看题目,这不就是一个很简单的问题吗?我直接一个双重for循环每次求出从i到j的累加和,内层循环每次取最短长度不就出来了,于是上代码:

var minSubArrayLen = function(target, nums) {
  let res = nums.length + 1;
  let len = 0;
  let sum = 0;
  for (let i = 0; i < nums.length; i++) {
     sum = 0;
    for (let j = i; j < nums.length; j++) {
      sum += nums[j];
      if (sum >= target) {
        len = j - i + 1;
        res = Math.min(len, res);
        break
      }
    }
  }
  return res > nums.length ? 0 : res;
  }

然后信心百倍的提交运行,不出意外通过了,就是时间优点长,我都想炫耀一下了。

image.png 那么是不是可以优化一下呢,如果就这么简单就过了,应该不会定义为中等难度,显然这不是出题者想要考察的内容,面试遇到你要是直接写出这样的答案,估计面试官就直接喊你回家了:“HR你叫人来面试都不筛选的吗?这都是些什么妖魔鬼怪!”

image.png
于是,为了不被面试官连人带椅子抬出去,我仔细思考了10分钟,感觉应该用滑动窗口,但总是差点东西,又写了10分钟,还是没写出来,果断看题解,瞬间豁然开朗,关掉题解,又是10分钟过去了。

image.png
然后再老老实实的把题解背了一遍,这里贴上滑动窗口的定义,所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果。首先我们要明白三点:
1.滑动窗口的内容是什么?满足条件的最小子数组的长度
2.滑动窗口的起始位置?窗口的个端点
3.何时该移动起始位置?当窗口的累计和大于等于目标值时,应该移动左端点;小于目标值时,应该移动右端点
所以可以得出窗口移动时候的伪代码:
1.计算窗口长度
2.判断当前窗口长度与上一轮循环后的最小值大小,取最小值
3.当前窗口累加和减去开始端点值,起点右移

代码实现

var minSubArrayLen = function(target, nums) {
//    // 滑动窗口解法
   let sum = 0; // 累加和
   let len = nums.length+1; // 最小长度
   let currentLen = 0 // 当前最小长度
   let i = 0 ; // 滑动窗口起点
   for(let j=0;j<nums.length;j++){ // j表示滑动窗口终点
       sum += nums[j]
       while(sum>=target){ // 累加和大于目标值 ,说明左边改移动了
          currentLen = j - i + 1 // 当前子数组长度
          len = currentLen < len ? currentLen:len
          sum -= nums[i]
          i++ // 起始右移
          
       }
       console.log(len)
   }

   return  len > nums.length ? 0 :len

};