滑动窗口算法_滑动窗口算法最简单的教程(2)

在滑动窗口算法最简单的教程(1)中,我们已经知道了,滑动窗口要解决的问题就是重复计算。这一点是滑动窗口问题的核心思想。今天要讲的这道题,比之前的问题要复杂一丢丢,但是基本思想那是一样一样的。

1 先看问题

给定一个都是正数的数组和一个正数,找到长度最短的连续元素组成的子数组,使它的和大于或者等于。如果这样的子数组不存在,返回0。

为了便于理解,我们给出几个具体的例子。

例子1:

输入: [2, 1, 5, 2, 3, 2], S=7 输出: 2 解释: 和大于等于7的最小子数组是 [5, 2]

例子2:输入: [2, 1, 5, 2, 8], S=7 输出: 1 解释: 和大于等于7的最小子数组是 [8]

例子3:输入: [3, 4, 1, 1, 6], S=8 输出: 3 解释: 和大于等于8的最小子数组是 [3, 4, 1] 或者 [1, 1, 6]

2 思路分析

这个问题和滑动窗口算法最简单的教程(1)中的问题,有一点明显不同,就是滑动窗口的大小并不是固定的。窗口每滑动一步,窗口的起始点都要尽可能的收缩,因为我们要找的是最小的窗口。所以,我们的解决方案如下:

  • 1、从数组起始处开始连续累加元素,直到元素的和大于或等于
  • 2、这时得到的连续子数组就组成我们的当前滑动窗口。我们要做的就是找到最小的窗口,使得窗口内元素的和大于或等于。我们将当前滑动窗口的长度作为迄今为止最小的窗口长度(因为只有这一个窗口)。
  • 3、然后,我们在窗口右端再加进来一个元素,相当于窗口右端前进了一步。
  • 4、右端每前进一步,我们都尝试收缩窗口的左端,我们将一直收缩,直到窗口内元素的和再次小于。这么做的目的,正是为了找到最小的窗口。此时的收缩,可以理解成是在所有以当前窗口右端点为右端点的连续子数组中,查找符合条件的最小窗口。只不过这里,我们不用再从数组开头查找,而是直接从当前窗口左端点处开始查找。如果仔细体会,会发现,此时的滑动窗口算法,我们不仅复用了窗口内元素的求和,同时,也复用了窗口的左端点来避免从头开始的计算。左端的收缩也许要进行许多步,在每一步中,我们都需要做两件事儿:(1)检查一下当前窗口的长度是不是目前为止最小的,如果是,就记下来(2)将当前窗口左端的第一个元素从窗口中移除

以例子1为例,我们的算法可以示意如下:

0ca2f4bbe7ef871c93ab8e663c4c35ad.png
269db9798f7265f694ce1baf8cc68f28.png
3e3b9a3875cf0a70a5264eb23417906a.png

3 代码实现

import math

def smallest_subarray_with_given_sum(s, arr):
window_sum = 0
min_length = math.inf
window_start = 0

for window_end in range(0, len(arr)):
window_sum += arr[window_end] # 累加下一个元素
# 尽可能缩小窗口,直到窗口内元素的和小于S
while window_sum >= s:
min_length = min(min_length, window_end - window_start + 1)
window_sum -= arr[window_start]
window_start += 1
if min_length == math.inf:
return 0
return min_length
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
滑动窗口算法是一种用于解决一些查找满足一定条件的连续区间的性质的问题的思想或技巧。它可以将双层嵌套的循环问题转换为单层遍历的循环问题,从而降低时间复杂度。滑动窗口算法的步骤通常包括维护两个指针left和right,表示当前窗口的左右边界。通过移动右指针扩大窗口,直到窗口内的元素之和满足某个条件。然后,移动左指针缩小窗口,直到不能再缩小为止。在这个过程中,记录窗口的最小长度,并更新最小长度的值。最后返回最小长度。滑动窗口算法的优包括时间复杂度较低、空间复杂度较低、简单易懂。然而,滑动窗口算法也有一些缺,包括无法解决所有子串问题、可能存在重复计算和可能存在局限性。总的来说,滑动窗口算法是一种有效的解决特定类型问题的方法。\[1\]\[2\]\[3\] #### 引用[.reference_title] - *1* *3* [滑动窗口算法精讲(Sliding Window Algorithm)](https://blog.csdn.net/qq_39559641/article/details/122793321)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [滑动窗口算法](https://blog.csdn.net/m0_63951142/article/details/130671127)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值