文章目录

  • 引言
  • 1.固定窗口
    • 239. 滑动窗口最大值
  • 2.可变窗口
    • 209. 长度最小的子数组
    • 713. 乘积小于K的子数组
    • 904. 水果成篮

引言

  有些时候,我们需要获得数组或者字符串的连续子部分,这时候我们就可以考虑使用滑动窗口。nums[left,right]为滑动窗口,根据具体的要求,通过遍历的时候来改变 left和right 的位置,从而完成任务。滑动窗口主要处理连续问题,按类型主要有如下三种:

  1. 固定窗口大小
  2. 窗口大小不固定,求解最大的满足条件的窗口
  3. 窗口大小不固定,求解最小的满足条件的窗口

1.固定窗口

对于固定窗口,我们只需要固定初始化左右指针Ieft和right,分别表示的窗口的左右顶点,并且保证:
1、Ieft初始化为0,
2、初始化right,使得right -Ieft+1等于窗口大小,
3、同时移动Ieft和right,
4、判断窗口内的连续元素是否满足题目限定的条件。
4.1、如果满足,再判断是否需要更新最优解,如果需要则更新最优解。
4.2、如果不满足,则继续。

239. 滑动窗口最大值

给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回滑动窗口中的最大值。

示例:

输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
滑动窗口的位置 最大值


[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7

class Solution:def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:# 定义左右指针left,right = 0,kres =[]  # 存储滑动窗口内的最大值if len(nums) > 0:while right <= len(nums):maxValues = max(nums[left:right])res.append(maxValues)left += 1right += 1return reselse:return nums


239. 滑动窗口最大值,利用双端队列一次遍历

class Solution:def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:# 思路:利用单调队列性质与滑动窗口,构建滑动窗口内最大值的单调队列,这里存储的是下标,与存储元素一样n = len(nums)res = []# 双端队列q = collections.deque()for i in range(k):while q and nums[i] >= nums[q[-1]]:q.pop()q.append(i)# 构建了第一个窗口大小为k的单调队列,这里队列中存储的是下标,单调队列队首即为最大值对应的坐标res.append(nums[q[0]])for i in range(k,n):# 遍历元素大于单调队列末尾元素时,需要弹出,重新构建单调队列while q and nums[i] >= nums[q[-1]]:q.pop()q.append(i)# 当窗口不包含这个元素时,需要从单调队列中,从队首删除while q[0] <= i-k:q.popleft()res.append(nums[q[0]])return res

2.可变窗口

对于可变窗口,我们同样固定初始化左右指针,分别表示的窗口的左右顶点。后面有所不同,我们需要保证:
1、Ieft和right都初始化为0
2、right指针移动一步
3、判断窗口内的连续元素是否满足题目限定的条件
3.1如果满足,再判断是否需要更新最优解,如果需要则更新最优解。并尝试通过移动Ieft指针缩小窗口大小。循环执行3.1
3.2如果不满足,则继续。

209. 长度最小的子数组

给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl,numsl+1,...,numsr−1,numsr][nums_l, nums_{l+1}, ..., nums_{r-1}, nums_r][numsl​,numsl+1​,...,numsr−1​,numsr​] ,并返回其长度。如果不存在符合条件的子数组,返回 0

思路:

1、开始right向右滑动,使和变大。
2、当恰好>=s时,记录滑窗所包括的子数组长度res,若res 已有数值,需判断新值是否小于旧值,若是,更新res; left向右滑动。
3、判断是否仍>=s,若是,重复步骤2,3。若否,转步骤1。直到右边框到达最右边

class Solution:def minSubArrayLen(self, target: int, nums: List[int]) -> int:# 初始化left = 0sums = 0res = float('inf')  # 无穷大# 右指针移动for right in range(len(nums)):sums += nums[right]while sums >= target:# 判断新值是否小于旧值,如果是则更新if right - left + 1 < res:res = right - left + 1# 左指针向右移动sums -= nums[left]left += 1# 循环结束条件:sums<targetif res == float('inf'):return 0else:return res

713. 乘积小于K的子数组

给定一个正整数数组 nums。
找出该数组内乘积小于 k 的连续的子数组的个数。

示例:

输入: nums = [10,5,2,6], k = 100
输出: 8
解释: 8个乘积小于100的子数组分别为: [10], [5], [2], [6], [10,5], [5,2], [2,6], [5,2,6]。
需要注意的是 [10,5,2] 并不是乘积小于100的子数组。

思路:

步骤1:当left <= right且滑动窗口内的乘积小于k时,我们可以知道[Ieft,right].[left+1,right]…[right-1,right]均满足条件,因此,计数加right-left+1,然后移动右边界(滑动区间加大),看剩下的区间是否满足乘积小于k,如果小于k,重复步骤1,否则进行步骤2。
步骤2:当滑动窗口内的乘积大于等于k时,右移左边界(滑动区间减小),如果这个区间内乘积小于k,进入步骤1,否则重复步骤2

class Solution:def numSubarrayProductLessThanK(self, nums: List[int], k: int) -> int:# 初始化left = 0product = 1res = 0# 右指针先移动for right in range(len(nums)):product *= nums[right]# 乘积大于等于k时,移动左指针while left <= right and product >= k:product /= nums[left]left += 1# 循环结束条件为:product < k# 统计当前右边界下的子数组个数res += (right - left + 1)return res

904. 水果成篮

在一排树中,第 i 棵树产生 tree[i] 型的水果。
你可以从你选择的任何树开始,然后重复执行以下步骤:

  1. 把这棵树上的水果放进你的篮子里。如果你做不到,就停下来。
  2. 移动到当前树右侧的下一棵树。如果右边没有树,就停下来。

请注意,在选择一颗树后,你没有任何选择:你必须执行步骤 1,然后执行步骤 2,然后返回步骤 1,然后执行步骤 2,依此类推,直至停止。
你有两个篮子,每个篮子可以携带任何数量的水果,但你希望每个篮子只携带一种类型的水果。
用这个程序你能收集的水果树的最大总量是多少?

问题可以抽象为:要求一个最长的连续子序列,同时这个子序列的元素种类不能超过2种

用一个右指针right和左指针left。右指针用于往右探,左指针用于指示每一个新的子序列要从前面那个序列里继承哪一位。那么继承哪一位呢?实际上继承的是翻转的那一位。例如[1,2,1,3,3,3],right往右遍历的时候,如果当前的种类与left的种类不同,那么就令left=right,其中i就指示了下一个子序列的起点。

class Solution:def totalFruit(self, tree: List[int]) -> int:ans = 0 # 总量n = len(tree)left, right = 0, 0types = {}  # 篮子while right < n:# 当前水果不可加入if len(types) == 2 and types.get(tree[right]) is None:    types = {}right = left                           # j回退到最后一次翻转的位置else:  # 当前水果可加入types[tree[right]] = types.get(tree[right], 0) + 1if tree[right] != tree[left]:     # 水果有翻转 用i记录下翻转的位置left = rightright += 1ans = max(ans, sum(types.values()))return ans

思路:

模拟一个滑动窗口,维护变量 i 是最小的下标满足 [i, j] 是合法的子序列。
维护 count 是序列中各种类型的个数,这使得我们可以很快知道子序列中是否含有 3 种类型。

class Solution(object):def totalFruit(self, tree):ans = i = 0# 字典的子类,提供了可哈希对象的计数功能count = collections.Counter()for j, x in enumerate(tree):count[x] += 1while len(count) > 2:# i指针右移count[tree[i]] -= 1if count[tree[i]] == 0:del count[tree[i]]i += 1ans = max(ans, j - i + 1)return ans


如果对您有帮助,麻烦点赞关注,这真的对我很重要!!!如果需要互关,请评论或者私信!


leetcode—8.同向双指针—滑动窗口题型python解答相关推荐

  1. 【算法3】---滑动窗口(python)

    目录 算法3 --- 滑动窗口(python) :mega: `前言:` :sun_with_face: `基本思想:` :closed_book: `代码示例:` :triangular_flag_ ...

  2. Leetcode双指针滑动窗口相关题目

    滑动窗口 滑动窗口解决哪种问题? 滑动窗口解决给定两个字符串S和T,问你S中是否存在一个子串,包含T中的所有字符并且不含有其他字符. 窗口右指针向右移动,窗口增大,直到满足条件,这时候找到可行解. 窗 ...

  3. 11. Leetcode 713. 乘积小于K的子数组 (数组-同向双指针-滑动窗口)

    给定一个正整数数组 nums和整数 k .请找出该数组内乘积小于 k 的连续的子数组的个数.示例 1:输入: nums = [10,5,2,6], k = 100 输出: 8 解释: 8个乘积小于10 ...

  4. LeetCode算法题6:滑动窗口*

    文章目录 前言 一.无重复字符的最长子串 思路 1: 思路 2: 二.字符串的排列 思路 1: 思路 2: 思路 3: 思路 3 plus: 思路 3 plus plus: 思路 4: 思路 5: 总 ...

  5. 【leetcode个人练习记录】 滑动窗口的问题

    1.从本质上来看 ,滑窗是双指针,一根指针指向左端点,一根指针指向右端点. 2.右指针移动是可以表示扩张窗口,左指针移动表示缩小窗口. 3.如果当前元素满足需求时,可以挪动右指针尝试更优解,并且更新需 ...

  6. LeetCode 438. Find All Anagrams in a String--字符串-滑动窗口--C++,Python解法

    题目地址:Find All Anagrams in a String - LeetCode Given a string s and a non-empty string p, find all th ...

  7. LeetCode Longest Repeating Character Replacement(滑动窗口)

    问题:给出一个由大写字母构成的字符串,可以对字符串最多作k次操作,将一个字符转换为另外一个字符. 找出操作后最长的重复子串 思路:使用滑动窗口,及用一个长度为26的数组记录字符个数.初始时,窗口大小为 ...

  8. LeetCode 76. 最小覆盖子串(滑动窗口)

    1. 题目 给你一个字符串 S.一个字符串 T,请在字符串 S 里面找出:包含 T 所有字母的最小子串. 示例: 输入: S = "ADOBECODEBANC", T = &quo ...

  9. leetcode刷题笔记-数组-滑动窗口

    一.滑动窗口的常见问题分析 问题 给定一个含有 n 个正整数的数组和一个正整数 target . 找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, - ...

  10. [剑指offer]面试题第[59-1]题[Leetcode][第239题][JAVA][滑动窗口的最大值][单调队列][优先队列]

    [问题描述][困难] [解答思路] 1. 暴力 两层 for 循环,每次都从窗口中找最大值即可 时间复杂度:O(N^2) 空间复杂度:O(N) public int[] maxSlidingWindo ...

最新文章

  1. sudo执行脚本找不到环境变量解决方法
  2. 【深度学习问题整理】
  3. BeautifulSoup总结
  4. linux nohup 终端断了,linux 后台执行nohup 命令,终端断开无影响
  5. mysql约束_从零开始学 MySQL - SQL 约束分类
  6. 2017新生儿爆款名字出炉!90后的父母们最受欢迎的居然是.....
  7. 如何将markdown转换为wxml
  8. java线程如何避免死锁_Java面试问题,如何避免Java线程中的死锁?
  9. mysql 导入百万级数据 几种 java_百万级数据,如何迁移到MySQL?
  10. Android 游戏开发中横竖屏切换问题
  11. 关于秒杀的细节,了解多少
  12. [十大谬论]常见的逻辑谬误与批判方法
  13. Docker Registry 详解
  14. 收集12个经典的程序员段子
  15. 图像识别最好的算法,图片相似度识别算法
  16. java arraylist.add(),Java ArrayList add()方法与示例
  17. 大数据风控必看,挖掘学历数据中暗藏的还款意愿及还款能力
  18. 目标检测0-02:YOLO V3-网络结构输入输出解析
  19. 将自动化测试推向极限
  20. 云日记_登出操作个人中心页面js和jsp知识点补充

热门文章

  1. 关于asp.net C# 导出Excel文件 打开Excel文件格式与扩展名指定格式不一致的解决办法...
  2. Hadoop的基本结构介绍(原创)
  3. Flex 中使用 FileReference 的 download 方法下载文件时的缓存刷新问题
  4. 贝叶斯推断之最大后验概率(MAP)
  5. 浅入浅出数据结构(23)——图的概念、存储方式与拓扑排序
  6. JQuery simpleModal插件的使用-遁地龙卷风
  7. php curl 伪造IP来源的代码分享
  8. menuconfig 菜单配置
  9. ORACLE成果,天天10问(四)
  10. CSblog的学习记录