滑动窗口详解及其应用

仅供自己复习
借鉴李威大佬的

一、滑动窗口详解

滑动窗口说白了也是双指针的一种变体,不过区别在于最开始窗口里为空(也就是说左右指针指向同一个),然后不断移动右边的指针,直到满足某条件后再收缩左边的指针
所以一般是双层循环,第一层循环动右指针,第二层循环动左指针,然后满足某条件或终止条件就返回

自个儿总结了一个模板

	function window(s) {
		let left = right = 0
		// 初始化一些需要的东西
		.......
		while(left <= right) {
			// 扩宽右边
			// 除了长度还有一些其他限制,根据题意
			while(right < s.length && ...) { 
				...
				right++
			}

			// 得出结果的一些代码
			if(...) {
				...
			}

			// 收缩左边
			....
			left--
		}
		return ...
	}

二、滑动窗口的应用

1、无重复字符的最长子串
滑动窗口详解及其应用_第1张图片

	/**
	 * @param {string} s
	 * @return {number}
	 */
	var lengthOfLongestSubstring = function(s) {
	    let left = right = 0
	    let stack = []
	    let max = 0
	    while(left <= right) {
	        // right < s.length 很关键
	        while(stack.indexOf(s[right]) === -1 && right < s.length) {
	            stack.push(s[right])
	            right++     
	        }
	        max = Math.max(max, stack.length)
	        stack.shift()
	        left++
	    }
	    return max
	};

2、最小覆盖子串
滑动窗口详解及其应用_第2张图片
我在算法总结里也写了这道题,不过有点不一样

	/**
	 * @param {string} s
	 * @param {string} t
	 * @return {string}
	 */
	var minWindow = function(s, t) {
	    let left = right = 0
	    let len = Infinity, needLen = t.length
	    let needWord = {}, window = {}
	    let startIndex = 0
	    for(let i = 0; i < t.length; i++) {
	        if(!needWord[t[i]]) {
	            needWord[t[i]] = 0
	            window[t[i]] = 0
	        }
	        needWord[t[i]]++
	    }
	    // 这里的临界判断跟以前的用right 0 && right < s.length) {
	            if(needWord[s[right]] !== undefined) {
	                if(needWord[s[right]] > window[s[right]]) {
	                    needLen--
	                }
	                window[s[right]]++
	            }
	            right++
	        }
	
	        if(needLen === 0 && right - left < len) {
	            len = right - left
	            startIndex = left
	        }
	        
	        if(needWord[s[left]] !== undefined) {
	            if(window[s[left]] <= needWord[s[left]]) {
	                needLen++
	            } 
	            window[s[left]]--
	        } 
	        left++
	    }
	    return len === Infinity ? '' : s.slice(startIndex, startIndex + len)
	};

3、找到字符串中所有字母异位词
滑动窗口详解及其应用_第3张图片

	/**
	 * @param {string} s
	 * @param {string} p
	 * @return {number[]}
	 */
	var findAnagrams = function(s, p) {
	    let res = []
	    let left = right = 0
	    let needWord = {}, window = {}
	    let needLen = p.length
	    for(let i = 0; i < p.length; i++) {
	        if(!needWord[p[i]]) {
	            needWord[p[i]] = 0
	            window[p[i]] = 0
	        }
	        needWord[p[i]]++
	    }
	    while(left <= right) {
	        while(right < s.length && needLen > 0) {
	            if(needWord[s[right]]) {
	                if(needWord[s[right]] > window[s[right]]) {
	                    needLen--
	                }
	                window[s[right]]++
	            }
	            right++
	        }
	
	        if(needLen === 0 && right - left === p.length) {
	            res.push(left)
	        }
	
	        if(needWord[s[left]] !== undefined) {
	            if(needWord[s[left]] >= window[s[left]]) {
	                needLen++
	            }
	            window[s[left]]--
	        } 
	        left++
	    }
	    return res
	};

4、长度最小的子数组
滑动窗口详解及其应用_第4张图片
以前写的,也跟滑动窗口差不多

	/**
	 * @param {number} s
	 * @param {number[]} nums
	 * @return {number}
	 */
	var minSubArrayLen = function(s, nums) {
	    let left = 0, right = 0
	    let sum = 0
	    let count = Number.MAX_VALUE
	    while(right < nums.length) {
	        if(nums[right] >= s) {
	            return 1
	        }
	        sum += nums[right]
	        right++
	        while(sum >= s) {
	            count = Math.min(count, right - left)
	            sum -= nums[left]
	            left++
	        }
	    }
	    return count === Number.MAX_VALUE ? 0 : count
	};

重新写的

	/**
	 * @param {number} s
	 * @param {number[]} nums
	 * @return {number}
	 */
	var minSubArrayLen = function(s, nums) {
	    let left = right = 0
	    let cnt = Infinity
	    let sum = 0
	    while(left <= right) {
	        if(s[right] > s) {
	            return 1
	        }
	
	        while(right < nums.length && sum < s) {
	            sum += nums[right]
	            right++
	        }
	
	        if(sum >= s) {
	            cnt = Math.min(cnt, right - left)
	        }
	        sum -= nums[left]
	        left++
	    }
	    return cnt === Infinity ? 0 : cnt
	};

5、字符串的排列
滑动窗口详解及其应用_第5张图片

	/**
	 * @param {string} s1
	 * @param {string} s2
	 * @return {boolean}
	 */
	var checkInclusion = function(s1, s2) {
	    let left = right = 0
	    let needWord = {}, window = {}
	    let needLen = s1.length
	    for(let i = 0; i < s1.length; i++) {
	        if(!needWord[s1[i]]) {
	            needWord[s1[i]] = 0
	            window[s1[i]] = 0
	        }
	        needWord[s1[i]]++
	    }
	    while(left <= right) {
	        while(needLen > 0 && right < s2.length) {
	            if(needWord[s2[right]] !== undefined) {
	                if(needWord[s2[right]] > window[s2[right]]) {
	                    needLen--
	                }
	                window[s2[right]]++
	            }
	            right++
	        }
	
	        if(right - left === s1.length && needLen === 0) {
	            return true
	        }
	
	        if(needWord[s2[left]] !== undefined) {
	            if(needWord[s2[left]] >= window[s2[left]]) {
	                needLen++
	            }
	            window[s2[left]]--
	        }
	        left++
	    }
	    return false 
	};  

你可能感兴趣的:(算法)