sliding Window 滑动窗口力扣简单题

发布时间 2023-03-31 16:55:21作者: 菜小季

概述

算法面试过程中,经常会遇到求解满足某种条件的子串问题,对于这种类型的题,一般可以使用双指针滑动窗口解答,滑动窗口问题可以认为是一种特殊的双指针。

 

使用场景

滑动窗口法常用于求解满足某种条件的某段连续区间的最短或最长子序列(一般为子数组、子字符串等),如:

1)最小摘要

2)和大于给定目标值的最短子序列

3)无重复字符的最长子串

4)有k个不同字符的子串
滑动窗口的重要性质是:窗口的左边界和右边界永远只能向右移动,而不能向左移动。这是为了保证滑动窗口的时间复杂度是 O(n)。如果左右边界向左移动的话,这叫做“回溯”,算法的时间复杂度就可能不止 O(n)

 

算法思想

滑动窗口问题可以想象成队列,一端在push元素,另一端在pop元素,如下所示:

假设有数组[1 2 3  4 5 6 7 8] 求 返回数组中最大的值 假设三个为一组

一开始我们的想法是 1+ 2 +3 ,求出结果 接下来 1+ 3 +4 求出来 。以此类推很麻烦对不对

接下来我们可以用滑动窗口解决该问题。 首先还是 1+ 2 + 3 求出结果 接下来 2+ 3  -1 +4 求出的值 接下来 3+4  - 2 +5 以此类推求出结果 相比较于直接加会方便很多

 

 

接下来会推荐两道力扣的题目

首先是力扣的209题目

给定一个含有 n 个正整数的数组和一个正整数 target 。

找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

解题思路:

定义两个指针 left 和 right,分别表示滑动窗口的左右边界。初始时,left 和 right 都指向数组的第一个元素。

每一次迭代,先将 nums[right] 加入滑动窗口的和中,如果滑动窗口的和小于目标值 target,则将右指针 right 右移一位,继续迭代;如果滑动窗口的和大于等于目标值 target,则更新最小长度,将左指针 left 右移一位,继续迭代。直到滑动窗口的和小于目标值 target 并且右指针到达数组的末尾,算法结束。

 

 

利用Python

def minSubArrayLen(target, nums):
    n = len(nums)
    left = right = 0
    cur_sum = 0
    min_len = float('inf')
    while right < n:
        cur_sum += nums[right]
        while cur_sum >= target:
            min_len = min(min_len, right - left + 1)
            cur_sum -= nums[left]
            left += 1
        right += 1
    return min_len if min_len != float('inf') else 0

 

 

1456:定长子串中元音的最大数目

给你字符串 s 和整数 k 。

请返回字符串 s 中长度为 k 的单个子字符串中可能包含的最大元音字母数。

英文中的 元音字母 为(a, e, i, o, u)。

示例 1:

输入:s = "abciiidef", k = 3
输出:3
解释:子字符串 "iii" 包含 3 个元音字母。
示例 2:

输入:s = "aeiou", k = 2
输出:2
解释:任意长度为 2 的子字符串都包含 2 个元音字母。
示例 3:

输入:s = "leetcode", k = 3
输出:2
解释:"lee"、"eet" 和 "ode" 都包含 2 个元音字母。
示例 4:

输入:s = "rhythms", k = 4
输出:0
解释:字符串 s 中不含任何元音字母。
示例 5:

输入:s = "tryhard", k = 4
输出:1
 

提示:

1 <= s.length <= 10^5
s 由小写英文字母组成
1 <= k <= s.length

解题思路

 

可以使用滑动窗口来解决这个问题。首先,我们可以计算字符串 s 中从第 0 个位置开始的 k 个字符的元音字母数。然后,我们可以依次向右滑动窗口,并计算窗口中的元音字母数。每次滑动窗口时,我们只需要将窗口的左边界向右移动一位,并将窗口的右边界向右移动一位,然后计算新窗口中的元音字母数。我们可以保留窗口中元音字母数的最大值,并在移动窗口时更新它。这样,当我们滑动窗口到字符串 s 的末尾时,我们就可以得到最大元音字母数。

具体地,我们可以使用一个计数器来记录窗口中的元音字母数。在初始化窗口时,我们可以遍历字符串 s 中的前 k 个字符,并使用计数器来计算元音字母的数量。然后,我们可以维护一个变量 max_vowels 来存储窗口中的最大元音字母数。在滑动窗口时,我们首先从窗口的左边界中减去第一个字符的贡献,然后从窗口的右边界中加上一个新字符的贡献,最后更新 max_vowels 变量。我们可以通过比较 max_vowels 和当前窗口中的元音字母数来更新它。最后,我们返回 max_vowels。

 

class Solution:
    def maxVowels(self, s: str, k: int) -> int:
        vowels = set(['a', 'e', 'i', 'o', 'u'])
        max_vowels = 0
        curr_vowels = 0
        for i in range(k):
            if s[i] in vowels:
                curr_vowels += 1
        max_vowels = curr_vowels
        for i in range(k, len(s)):
            if s[i] in vowels:
                curr_vowels += 1
            if s[i - k] in vowels:
                curr_vowels -= 1
            max_vowels = max(max_vowels, curr_vowels)
        return max_vowels