【leetcode】双指针算法技巧——滑动窗口

标题:【leetcode】双指针算法技巧——滑动窗口

@水墨不写bug 


正文开始:

 

滑动窗口介绍 

        滑动窗口是一种常用的算法技巧,用于解决一些涉及  连续子数组或子串  的问题。它的基本思想是  维护一个窗口,通过  在窗口内移动  来寻找满足特定条件的子数组或子串。

滑动窗口算法的步骤如下:

  1. 初始化窗口的起始位置left和终止位置right。
  2. 在每一步迭代中,将窗口右移一位,即将right加1,并根据题目要求更新窗口的状态。
  3. 如果窗口的状态满足题目给定的条件,那么根据题目要求处理结果。
  4. 如果窗口的状态不满足题目给定的条件,那么将窗口左移一位,即将left加1,继续迭代。

滑动窗口算法的时间复杂度通常为O(n),其中n是数组或字符串的长度。它的优势在于可以将一些问题的时间复杂度从O(n^2)降低到O(n)。

四个必要步骤 

滑动窗口的四个必要步骤:

        (1)入窗口

        (2)判断

        (3)出窗口

        (4)更新结果 

对于前三条,它们的顺序一般相对彼此是固定的。更新结果的位置放在何处,需要根据题意判断。


(一)长度最小的子数组

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

        找出该数组中满足其总和大于等于 target 的长度最小的 连续子数组 

[nums , nums + 1, ... , nums + r-1, nums + r] ,并返回其长度如果不存在符合条件的子数组,返回 0 。

示例 1:

输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。

示例 2:

输入:target = 4, nums = [1,4,4]
输出:1

示例 3:

输入:target = 11, nums = [1,1,1,1,1,1,1,1]
输出:0

提示:

  • 1 <= target <= 10^9
  • 1 <= nums.length <= 10^5
  • 1 <= nums[i] <= 10^5

进阶:

  • 如果你已经实现 O(n) 时间复杂度的解法, 请尝试设计一个 O(n log(n)) 时间复杂度的解法。

        思路一:

        找出所有的情况,遍历出所有sum==k的情况,分别求其长度,找出最小的长度即可。

以用例 1 具体来说:

[  2  ,  3  ,  1  ,  2  ,  4  ,  3  ]

        创建left指针标记第一个元素,创建一个right指针向后遍历,同时将两指针之间的元素求和sum,如果sum==k,将此时的len存入数组ret,最终再找出ret中的最小值即可。

        更优的算法从哪里来?是从暴力算法优化而来的!

        思路二:

        从宏观上我们先让sum尽可能的和k的值相近,这样才可能满足sum与k相等。假设我们此时确定了一个区间:

为了满足条件,

        如果sum < k,继续增加sun的值;

        如果sum==k,记录len(挑最小的记录);

        如果sum > k,则要减小sum的值;

现在就是确定如何加任何减的问题了。由于区间是连续的,不能有间断,所以从习惯上选择从左向右遍历,移动窗口。

        这样我们就知道了,

        left++,left指针向后移动实现减小sum(出窗口)

        right++,right指针向后移动实现增加sum(入窗口)

参考代码: 

class Solution {
public:int minSubArrayLen(int target, vector<int>& nums) {int n = nums.size(),len = INT_MAX,sum = 0;/*将len初始化为很大的数,防止被求最小值的实际长度干扰*/for(int left = 0,right = 0;right < n;++right){//进窗口,sum维护sum += nums[right];while(sum >= target)//判断{len = min(len,right-left + 1);//更新结果sum -= nums[left++];//出窗口 }}return len == INT_MAX ? 0 : len;}
};

(二)无重复字符的最长字串

给定一个字符串 s ,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:

输入: s = "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是"abc",所以其长度为 3。

示例 2:

输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是"b",所以其长度为 1。

示例 3:

输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

提示:

  • 0 <= s.length <= 5 * 10^4
  • s 由英文字母、数字、符号和空格组成

让滑动窗口满足:窗口内所有元素都是不重复的。


做法:右端元素 ch 进⼊窗口的时候,哈希表统计这个字符的频次:
▪ 如果这个字符出现的频次超过 1 ,说明窗口内有重复元素,那么就从左侧开始划出窗口,
直到 ch 这个元素的频次变为 1 ,然后再更新结果。
▪ 如果没有超过 1 ,说明当前窗口没有重复元素,可以直接更新结果。
 

参考代码:

class Solution {
public:int lengthOfLongestSubstring(string s) {int left = 0,right = 0,n = s.size(),ret = 0;int hash[128] = {0};//使用数组模拟哈希表while(right < n){hash[s[right]]++;//进入窗口//判断while(hash[s[right]] > 1){hash[s[left++]]--;//出窗口}ret = max(ret,right - left + 1);right++;}return ret;}
};

(三)最大连续1的个数

给定一个二进制数组 nums 和一个整数 k,如果可以翻转最多 k 个 0 ,则返回 数组中连续 1 的最大个数 。

示例 1:

输入:nums = [1,1,1,0,0,0,1,1,1,1,0], K = 2
输出:6
解释:[1,1,1,0,0,1,1,1,1,1,1]
粗体数字从 0 翻转到 1,最长的子数组长度为 6。

示例 2:

输入:nums = [0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,1,1,1], K = 3
输出:10
解释:[0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1]
粗体数字从 0 翻转到 1,最长的子数组长度为 10。

提示:

  • 1 <= nums.length <= 10^5
  • nums[i] 不是 0 就是 1
  • 0 <= k <= nums.length

        不要自找麻烦,思路其实很简单;

要换个角度思考->

        这道题的结果无非就是⼀段连续的 1 中间塞了 k 个 0 嘛。
        我们可以把问题转化成:求数组中一段最长的连续区间,要求这段区间内 0 的个数不超过 k 个。

参考代码: 


class Solution {
public:int longestOnes(vector<int>& nums, int k) {int hash[2] = {0};int n = nums.size(),ret = 0;//if(k >= n) return n;for(int right = 0,left = 0 ; right < n ; right++){hash[ nums[right] ]++;//进窗口while(hash[0] > k)//判断{hash[ nums[left++] ]--;//出窗口}ret = max(ret,right-left+1);}return ret;}
};

(四)将x减小到0的最小操作数

给你一个整数数组 nums 和一个整数 x 。每一次操作时,你应当移除数组 nums 最左边或最右边的元素,然后从 x 中减去该元素的值。请注意,需要 修改 数组以供接下来的操作使用。

如果可以将 x 恰好 减到 0 ,返回 最小操作数 ;否则,返回 -1 。

示例 1:

输入:nums = [1,1,4,2,3], x = 5
输出:2
解释:最佳解决方案是移除后两个元素,将 x 减到 0 。

示例 2:

输入:nums = [5,6,7,8,9], x = 4
输出:-1

示例 3:

输入:nums = [3,2,20,1,1,3], x = 10
输出:5
解释:最佳解决方案是移除后三个元素和前两个元素(总共 5 次操作),将 x 减到 0 。

提示:

  • 1 <= nums.length <= 10^5
  • 1 <= nums[i] <= 10^4
  • 1 <= x <= 10^9

         题目要求的是数组「左端+右端」两段连续的、和为 x 的最短数组;

换一个角度思考->

        我们可以转化成求数组内⼀段连续的、和为 sum(nums) - x 的最长数组。此时,就是熟
悉的「滑动窗口」问题了
本质和 (一)长度最小的子数组 是相同的代码结构,就一点不同——需要记录的数组长度从记录最小变成了记录最大。

参考代码: 

class Solution {
public:int minOperations(vector<int>& nums, int x) {int sum_all = 0,n = nums.size();for(int i = 0;i < n;i++){sum_all += nums[i];}int target = sum_all - x,sum = 0,left = 0,right = 0,ret = -1;if(target == 0) return n;for(;right < n;right++){sum += nums[right];//进窗口if(sum > target)//判断,right最佳位置{while(sum > target && (left < right)){sum -= nums[left++];//出窗口} }if(sum == target){ret = max(ret,right-left+1);}}if(ret == -1) return ret;else return n - ret;}
};

完~

未经作者同意禁止转载

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/823091.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何查询RGB图像的三维numpy数组中有多少个不同的RGB点,并打印具体数值?

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

xgplayer插件的使用-西瓜播放器 ---- Vue3中使用

xgplayer 视频 一、xgplayer官网 xgplayer官网 - 点我进入 一、xgplayer简单介绍 西瓜播放器是字节跳动推出的一款播放器。 稳定性好&#xff08;大厂&#xff08;字节跳动&#xff09;出品&#xff09;&#xff1b;插件方便实用且简洁高雅&#xff1b;官网文档清晰&#xff1b…

[Linux - C] 自主Shell

[Linux - C] 自主Shell [Linux - C语言] 自主Shell逻辑策划 main()打印命令行 void MakeCommandLineAndPrint()用户名 USER主机名 HOSTNAME当前目录 PWDSkipPath 切割目录打印命令行 获取用户字符串 int GetUserCommand()检查重定向 void CheckRedir()切割字符 void SplitComma…

数据加密、文档加密为什么都选择安企神软件

数据加密、文档加密为什么都选择安企神软件 免费试用安企神 在数据加密和文件加密领域&#xff0c;有众多优秀的软件&#xff0c;他们功能各异、价格不同、效果也大相径庭&#xff0c;经过对比使用、用户口碑和技术网站评判&#xff0c;安企神在各方面都稳坐第一把交易。其原…

新闻媒体行业邮件推广:精准推送,创造价值

在当今信息爆炸的时代&#xff0c;新闻行业如何在竞争激烈的市场中脱颖而出&#xff0c;吸引读者的目光&#xff0c;成为了每个新闻机构都需要认真思考的问题。许可式邮件营销成为了一种强大的工具&#xff0c;不仅能够向订阅者发送新闻期刊&#xff0c;还能够向广告商发送宣传…

【基础物理实验】【AFM虚拟实验】基于AFM的物质表面微观结构及力学性质表征仿真实验(下)【北京航空航天大学】

本次实验&#xff08;上&#xff09;见博客&#xff1a;【基础物理实验】【AFM虚拟实验】基于AFM的物质表面微观结构及力学性质表征仿真实验&#xff08;上&#xff09;【北京航空航天大学】 本次实验&#xff08;中&#xff09;见博客&#xff1a;【基础物理实验】【AFM虚拟实…

LLamaSharp加载llama.cpp转化好的模型

新建.net8控制台项目 安装依赖包 LLamaSharp和LLamaSharp.Backend.Cpu 准备好转化好的模型 没有的话参考这篇文章https://blog.csdn.net/qq_36437991/article/details/137248622 编写代码 using LLama; using LLama.Common; using LLama.Native;namespace llamasharpstu…

N皇后问题(DFS解决)

文章目录 一、题目分析二、对角线判断&#xff08;分两种&#xff09;三、代码演示 先赞后看&#xff0c;养成习惯&#xff01;&#xff01;&#xff01;^ _ ^<3 ❤️ ❤️ ❤️ 码字不易&#xff0c;大家的支持就是我坚持下去的动力。点赞后不要忘了关注我哦&#xff01; 一…

全球7大指纹浏览器排行榜:哪个最适合你?

在数字时代&#xff0c;我们每一次上网都会留下独特的数字足迹&#xff0c;被称为“浏览器指纹”。为了保护这些私人信息不被滥用&#xff0c;指纹浏览器成为了一个重要工具。但是&#xff0c;并非所有的指纹浏览器都是一样的&#xff0c;它们各有特点&#xff0c;适用于不同的…

数字乡村创新实践探索农业现代化路径:科技赋能农业产业升级、提升乡村治理效能与农民幸福感

随着信息技术的快速发展和数字化时代的到来&#xff0c;数字乡村建设正成为推动农业现代化、提升农业产业竞争力、优化乡村治理以及提高农民幸福感的重要途径。本文将围绕数字乡村创新实践&#xff0c;探讨其在农业现代化路径中的积极作用&#xff0c;以及如何通过科技赋能实现…

28. 找出字符串中第一个匹配项的下标(KMP)

class Solution {public int[] getNext(int[] next,String s){//j有两层含义&#xff1a;&#xff08;1&#xff09;最长公共前后缀的长度&#xff08;2&#xff09;前缀的末尾&#xff0c;是即将匹配的那个位置int j 0;//i含义&#xff1a;后缀的末尾&#xff0c;是即将匹配的…

Python疑难杂症(20)---介绍Python的pandas模块中将数据导入内存和导出数据的方法,以及一些参数的用法。

Python的pandas模块中数据框这种数据类型&#xff0c;可以通过文件导入函数&#xff0c;将磁盘上的csv、execl等类型的文件装入内存&#xff0c;并生成数据框的格式&#xff0c;以方便后续使用pandas的专有方法进行处理。 6、DataFrame数据输导入导出方法 Pandas常用的读取数…

安装ps提示MSVCP140.dll丢失怎么办,推荐几种有效的解决方法

在成功完成Adobe Photoshop&#xff08;简称PS&#xff09;软件的安装过程之后&#xff0c;当用户试图启动并运行该程序时&#xff0c;系统却弹出了一个令人困扰的错误提示信息&#xff0c;明确指出&#xff1a;“无法找到MSVCP140.dll”这一关键文件。这意味着尽管PS软件已经成…

redmibook 14 2020 安装 ubuntu

1. 参考博客 # Ubuntu20.10系统安装 -- 小米redmibook pro14 https://zhuanlan.zhihu.com/p/616543561# ubuntu18.04 wifi 问题 https://blog.csdn.net/u012748494/article/details/105421656/# 笔记本电脑安装了Ubuntu系统设置关盖/合盖不挂起/不睡眠 https://blog.csdn.net/…

权威Scrum敏捷开发企业级实训/敏捷开发培训课程

课程简介 Scrum是目前运用最为广泛的敏捷开发方法&#xff0c;是一个轻量级的项目管理和产品研发管理框架。 这是一个两天的实训课程&#xff0c;面向研发管理者、项目经理、产品经理、研发团队等&#xff0c;旨在帮助学员全面系统地学习Scrum和敏捷开发, 帮助企业快速启动敏…

【机器学习】科学库使用第5篇:Matplotlib,学习目标【附代码文档】

机器学习&#xff08;科学计算库&#xff09;完整教程&#xff08;附代码资料&#xff09;主要内容讲述&#xff1a;机器学习&#xff08;常用科学计算库的使用&#xff09;基础定位、目标&#xff0c;机器学习概述定位,目标,学习目标,学习目标,1 人工智能应用场景,2 人工智能小…

【网络设备巡检命令】--思科、华为、H3C、锐捷

【网络设备巡检命令】--思科、华为、H3C、锐捷 一、思科二、华为三、H3C四、锐捷 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 一、思科 1、查看系统信息&#xff1a; show version2、查看时间&#xff1a; show clock3、查看序列号&a…

Nginx内存池相关源码剖析(三)小块内存分配逻辑

在Nginx中&#xff0c;小块内存通常指的是那些大小相对较小、分配和释放频率较高的内存块。这些内存块由于数量众多、管理复杂&#xff0c;因此需要使用一种高效的内存管理机制来减少内存管理的开销和内存碎片的产生。 Nginx内存池通过一种预分配和复用的方式来管理小块内存。当…

觉飞、希亦、Daily neaty内衣洗衣机好用吗?爆款产品性能全面测评!

近几年来小家电产品中&#xff0c;内衣洗衣机的讨论热度无疑是最大的&#xff0c;功能多、操作方便&#xff0c;用内衣洗衣机来清洗内衣裤会更加卫生和安全&#xff0c;能满足了消费者的多种需求。不过尽管市面上的内衣洗衣机品牌很多、挑选空间大&#xff0c;也不是所有产品都…

RT-thread-线程间通讯3-事件集

事件集 事件集也是线程间同步的机制之一,一个事件集可以包含多个事件,利用事件集可以完成一对多,多对多的线程间同步。 一个线程和多个事件的关系可设置为: 其中任意一个事件唤醒 线程,或几个事件都到达后唤醒线程,多个事件集合可以用一个32bit无符号整型变量来表示,…