滑动窗口用法

本文详细解释并展示了如何使用编程解决五个与字符串操作相关的问题:长度最小的子数组、无重复字符的最长子串、最小覆盖字串、加油站问题以及替换字符得到平衡字符串。通过代码实现和分析步骤,展示了如何利用窗口滑动策略优化求解过程。

1. 长度最小的子数组(模板)

image-20240310211503255

  1. 题目分析
直接用步骤分析示例1,[]表示窗口,min_length表示满足条件的最短子数组,sum表示窗口内元素的总值:
	- [2],3,1,2,4,3		min_length=100001,sum=2 < target=7
	- [2,3],1,2,4,3		min_length=100001,sum=5 < target=7
	- [2,3,1],2,4,3		min_length=100001,sum=6 < target=7
	- [2,3,1,2],4,3		min_length=4,     sum=8 >= target=7
	- PS:只要sum>=target,就尝试将左窗口向右移动,若仍满足条件,就更新min_length,不行就继续
	- [2,3,1,2,4],3		min_length=5,	  sum=12 >= target=7
	- 2,[3,1,2,4],3		min_length=4,	  sum=10 >= target=7
	- 2,3,[1,2,4],3		min_length=3,	  sum=7 >= target=7
	- 2,3,[1,2,4,3]		min_length=4,	  sum=10 >= target=7
	- 2,3,1,[2,4,3]		min_length=3,	  sum=9 >= target=7
	- 2,3,1,2,[4,3]		min_length=2,	  sum=7 >= target=7
	- 最后返回min_length=2
  1. 代码实现
def minSubArrayLen(target, nums):
    """
    :type target: int
    :type nums: List[int]
    :rtype: int
    """
    n = len(nums)
    
    # l表示左窗口的位置,r表示右窗口的位置
    l = r = 0
    # sum表示窗口内的元素总值
    sum = nums[0]
    
    # 如果第一个元素的值就大于等于target,直接返回
    if sum >= target:   
        return 1
    
    # 设置成100001是因为测试用例的数组长度最长为100000
    min_length = 100001
    
    # 循环n - 1次
    for i in range(1, n):
        # 右窗口肯定是要一直移动的,不存在每次循环不移动的情况
        r += 1
        sum += nums[r]
        
        # 如果sum去掉靠近左窗口的那个元素后仍然大于sum,就该减小窗口的长度了
        while sum - nums[l] >= target:
            sum -= nums[l]
            l += 1
        
        # 经过上述步骤后,当来到右窗口此时的位置时,满足条件的窗口长度就得到了
        if sum >= target:
            min_length = min(min_length, r - l + 1)
    
    # 数组所有元素的总和加起来都小于target,min_length就返回0
    return 0 if min_length == 100001 else min_length

image-20240310215745912

  1. 精简版
def minSubArrayLen(target, nums):
    """
    :type target: int
    :type nums: List[int]
    :rtype: int
    """
    n = len(nums)

    l = r = 0

    min_length = 100001

    sum = 0

    while r < n:
        sum += nums[r]

        while sum - nums[l] >= target
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值