滑动窗口算法

接下来就开始介绍数组操作中另一个重要的方法:滑动窗口

所谓滑动窗口,就是不断的调节子序列的起始位置和终止位置,从而得出我们要想的结果

在暴力解法中,是一个for循环滑动窗口的起始位置,一个for循环为滑动窗口的终止位置,用两个for循环 完成了一个不断搜索区间的过程。

那么滑动窗口如何用一个for循环来完成这个操作呢。

首先要思考 如果用一个for循环,那么应该表示 滑动窗口的起始位置,还是终止位置。

如果只用一个for循环来表示 滑动窗口的起始位置,那么如何遍历剩下的终止位置?

此时难免再次陷入 暴力解法的怪圈。

所以 只用一个for循环,那么这个循环的索引,一定是表示 滑动窗口的终止位置。

那么问题来了, 滑动窗口的起始位置如何移动呢?

这里还是以题目中的示例来举例,s=7, 数组是 2,3,1,2,4,3,来看一下查找的过程:

最后找到 4,3 是最短距离。

其实从动画中可以发现滑动窗口也可以理解为双指针法的一种!只不过这种解法更像是一个窗口的移动,所以叫做滑动窗口更适合一些。

在本题中实现滑动窗口,主要确定如下三点:

  • 窗口内是什么?
  • 如何移动窗口的起始位置?
  • 如何移动窗口的结束位置?

窗口就是 满足其和 ≥ s 的长度最小的 连续 子数组。

窗口的起始位置如何移动:如果当前窗口的值大于s了,窗口就要向前移动了(也就是该缩小了)。

窗口的结束位置如何移动:窗口的结束位置就是遍历数组的指针,也就是for循环里的索引。

解题的关键在于 窗口的起始位置如何移动,如图所示:

然后我们利用上面的算法完成如下的题:

#滑动窗口法
target=int(input())  # 输入目标值并将其转换为整数
n=list(map(int,input().split(",")))  # 输入一串以逗号分隔的数字,并将其转换为整数数组
l=len(n)  # 数组n的长度
left=0  # 子数组的左边界指针
right=0  # 子数组的右边界指针
min_len = float('inf')  # 记录当前最小子数组的长度,初始值设为正无穷
cur_sum = 0  # 当前的累加值,用于计算子数组的元素之和

while right < l:  # 当右边界指针小于数组长度时循环执行以下操作
    cur_sum += n[right]  # 将n[right]值加到当前累加值cur_sum中

    while cur_sum >= target:  # 当当前累加值cur_sum大于等于目标值target时循环执行以下操作
        min_len = min(min_len, right - left + 1)  # 更新最小子数组的长度
        cur_sum -= n[left]  # 从当前累加值cur_sum中减去n[left]的值
        left += 1  # 左边界指针右移

    right += 1  # 右边界指针右移

print(min_len) if min_len != float('inf') else 0  # 输出最小子数组的长度(如果存在),否则输出0

left和right: 指向子数组的左右边界
min_len: 记录当前最小子数组的长度,初始值设为正无穷
cur_sum: 记录当前子数组的元素之和,初始值为0
代码同样使用两个指针left和right来构建一个滑动窗口。right指针向右移动,每次将n[right]添加到当前子数组的元素之和cur_sum中。如果cur_sum大于等于目标值target,说明找到了一个符合要求的子数组。

此时,需要不断移动left指针以缩小子数组的长度,同时更新min_len的值。left指针每次右移,需要将n[left]从cur_sum中减去,并更新left的位置。

当right指针到达数组的末尾时,算法结束,输出min_len作为结果。如果初始的min_len值仍为正无穷,则说明没有找到符合要求的子数组,输出0。

这种方法的时间复杂度是O(n),其中n是数组n的长度。算法只需要遍历一遍数组,通过移动left和right指针,不断更新cur_sum和min_len的值。

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值