JavaScript滑动窗口算法

JavaScript滑动窗口算法

  • 1 思想
  • 2 代码

1 思想

在力扣上刷题时经常可以看到这样的题,求XXX的子串、子数组、子序列等等,这类题一般使用滑动窗口来解决。本篇文章的思路学习了bilibili的up主红桃A士。

情况一:寻找最长的

①初始化左右指针left和right,左右指针之间的内容就是窗口,定义一个变量result记录当前的滑动窗口的结果,定义一个变量bestResult记录当前滑动窗口下的最优结果
②right要向右逐位滑动循环
③每次滑动后,记录当前滑动的结果。如果当前的结果符合条件,则更新最优的结果,然后right要继续向右滑动;如果当前的结果不符合条件,那么要让left逐步收缩
④当right到达结尾时停止滑动

初始化left,right,result,bestResult
while (右指针没有到结尾) {
    窗口扩大,加入right对应元素,更新当前result
    while (result不满足要求) {
        窗口缩小,移除left对应元素,left右移
    }
    更新最优结果bestResult
    right++;
}
返回bestResult

情况二:寻找最短的

①初始化左右指针left和right,左右指针之间的内容就是窗口,定义一个变量result记录当前的滑动窗口的结果,定义一个变量bestResult记录当前滑动窗口下的最优结果
②right要向右逐位滑动循环
③每次滑动后,记录当前滑动的结果。如果当前的结果符合条件,则更新最优的结果,然后right要继续向右滑动;如果当前的结果不符合条件,那么要让left逐步收缩
④当right到达结尾时停止滑动

初始化left,right,result,bestResult
while (右指针没有到结尾) {
    窗口扩大,加入right对应元素,更新当前result
    while (result不满足要求) {
    	更新最优结果bestResult
        窗口缩小,移除left对应元素,left右移
    }
    right++;
}
返回bestResult

2 代码

下面以力扣的两道题来说明两种情况。

1、寻找最长的

力扣3. 无重复字符的最长子串

给定一个字符串 s ,请你找出其中不含有重复字符的最长子串的长度。

示例 1:
输入: s = “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。

示例 2:
输入: s = “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。

示例 3:
输入: s = “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。

var lengthOfLongestSubstring = function (s) {
    let left = right = len = maxLen = 0;
    let arr = []; // 记录当前滑动窗口包含的字符

    // 当右指针指向字符串最右边时停止循环
    while (right < s.length) {
        if (arr.includes(s[right])) { // 如果滑动窗口中的字符串包含了右指针指向的元素
            // 当arr中不包含右指针指向的字符,停止循环
            while (arr.includes(s[right])) {
                arr.shift(); // 删除最左边的元素
                len--; // 更新当前的长度
                left++; // 左指针右移
            }
            // 循环结束后,arr中不包含右指针指向的元素
            arr.push(s[right]);
            len++;
            right++;
        } else { // 如果滑动窗口中的字符串不包含右指针指向的元素
            arr.push(s[right]);
            len++; // 更新当前状态
            if (len > maxLen) { // 如果当前长度大于记录的最大长度,则更新最大长度
                maxLen = len;
            }
            right++;
        }
    }
    return maxLen;
};

2、寻找最短的

力扣209. 长度最小的子数组

给定一个含有 n 个正整数的数组和一个正整数 target 。找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

示例 1:
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。

示例 2:
输入:target = 4, nums = [1,4,4]
输出:1

示例 3:
输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0

var minSubArrayLen = function (target, nums) {
    let left = 0, right = 0; // 定义左右指针
    let result = 0; // 记录当前滑动窗口的值
    let bestResult = 0; // 记录最优的值
    while (right < nums.length) { // 右指针移动到最右边《结束循环
        result = result + nums[right]; // 记录当期滑动窗口的值
        while (result >= target) {
            // 如果当前的最好的结果大于左右指针之间的长度,更新最优结果
            if (right - left + 1 < bestResult || bestResult == 0) {
                bestResult = right - left + 1;
            }
            // 将左指针向右移,并且左指针的值从当前结果里面减掉
            result -= nums[left];
            left++;
        }
        right++; // 向右滑动窗口
    }
    return bestResult;
};

你可能感兴趣的:(数据结构,javascript,滑动窗口)