算法思想总结:双指针算法

一、移动零

. - 力扣(LeetCode) 移动零

该题重要信息:1、保持非0元素的相对位置。2、原地对数组进行操作

 思路:双指针算法

class Solution {
public:void moveZeroes(vector<int>& nums){int n=nums.size();for(int cur=0,des=-1;cur<n;++cur)if(nums[cur])//如为非零,就要与des后面的位置元素进行交换swap(nums[++des],nums[cur]);}
};

 二、复写零

. - 力扣(LeetCode)复写零

该题的重要信息:1、不要在超过该数组的长度的位置写入元素(就是不要越界)2、就地修改(就是不能创建新数组)。3、不返回任何东西。

 思路:双指针算法

class Solution {
public:void duplicateZeros(vector<int>& arr){int cur=0,des=-1,n=arr.size();//找最后一个被复写数的位置for(;cur<n;++cur){if(arr[cur])++des;elsedes+=2;if(des>=n-1)//要让des指向最后一个位置break;}//边界修正if(des==n){arr[--des]=0;--des;--cur;}//从后往前复写for(;cur>=0;--cur){if(arr[cur])arr[des--]=arr[cur];else{arr[des--]=0;arr[des--]=0;}}}
};

 三、快乐数

. - 力扣(LeetCode)快乐数

 该题的关键是:将正整数变成他的每位数的平方之和,有可能会一直循环始终到不了1,也有始终是1(快乐数)

思路:快慢双指针算法

以上的两个结论在博主的关于链表带环追击问题的文章里面有分析

顺序表、链表相关OJ题(2)-CSDN博客

class Solution {
public:int bitsum(int n){ int sum=0;while(n){int t=n%10;sum+=t*t;n/=10;//最后一位算完后拿掉}return sum;}bool isHappy(int n) {int slow=n,fast=bitsum(n);while(fast!=slow){slow=bitsum(slow);fast=bitsum(bitsum(fast));}return slow==1;}
};

四、盛最多水的容器

. - 力扣(LeetCode)盛最多水的容器

思路1、暴力枚举(时间复杂度太高)

class Solution {
public:int maxArea(vector<int>& height){//暴力枚举int n=height.size();int ret=0;for(int i=0;i<n;++i)for(int j=i+1;j<n;++j)ret=max(ret,min(height[i],height[j])*(j-i));return ret;}
};

思路2、双指针对撞算法

class Solution {
public:int maxArea(vector<int>& height){int left=0,right=height.size()-1,ret=0;while(left<right){ret=max(ret,min(height[left],height[right])*(right-left));if(height[left]<height[right])++left;else--right;}return ret;}
};

五、有效三角形的个数

. - 力扣(LeetCode)有效三角形的个数

 思路1:升序+暴力枚举

思路2:升序+利用双指针算法

class Solution {
public:int triangleNumber(vector<int>& nums) {//排序一下sort(nums.begin(),nums.end());//先固定一个数,然后用双指针去找比较小的两个数int n=nums.size(),ret=0;for(int i=n-1;i>=2;--i){int left=0,right=i-1;while(left<right){int sum=nums[left]+nums[right];if(sum<=nums[i])  ++left;else  {ret+=(right-left);--right;} }}return ret;}
};

 六、查找总价格为目标值的两个商品

. - 力扣(LeetCode)查找总价格为目标值的两个商品

 

思路1:两层for循环找到所有组合去计算

思路2:利用单调性,使用双指针算法解决问题

class Solution {
public:vector<int> twoSum(vector<int>& price, int target) {int n=price.size();int left=0,right=n-1;while(left<right){int sum=price[left]+price[right];if(sum>target) --right;else if(sum<target) ++left;else return {price[left],price[right]};}return {1,0};}
};

七、三数之和

. - 力扣(LeetCode)三数之和

解法1:排序+暴力枚举+set去重

解法2:排序+双指针

class Solution {
public:vector<vector<int>> threeSum(vector<int>& nums){vector<vector<int>> ret;int n=nums.size();//先排序sort(nums.begin(),nums.end());//先固定一个数for(int i=0;i<n;){if(nums[i]>0) break;//小优化int target =-nums[i];//目标值//定义双指针int left=i+1,right=n-1;while(left<right){int sum=nums[left]+nums[right];if(sum<target)  ++left;else if(sum>target) --right;else  {ret.push_back({nums[left],nums[right],nums[i]});//插入进去++left;--right;//去重while(left<right&&nums[left]==nums[left-1])  ++left;//去重要注意边界while(left<right&&nums[right]==nums[right+1])  --right;}}++i;while(i<n&&nums[i]==nums[i-1])  ++i;//去重要注意边界}return ret;}
};

八、四数之和

. - 力扣(LeetCode)四数之和

解法1:排序+暴力枚举+set去重

解法2:排序+双指针(和上一题基本一样,无非就是多固定了一个数)

class Solution {
public:vector<vector<int>> fourSum(vector<int>& nums, int target) {vector<vector<int>> ret;//先进行排序sort(nums.begin(),nums.end());//利用双指针解决int n=nums.size();//先固定一个数for(int i=0;i<n;){//再固定一个数for(int j=i+1;j<n;){int left=j+1,right=n-1;long long aim=(long long)target-nums[i]-nums[j];//确保不超出范围while(left<right){long long sum=nums[left]+nums[right];if(sum<aim)  ++left;else if(sum>aim) --right;else {ret.push_back({nums[i],nums[j],nums[left],nums[right]});++left;--right;//去重while(left<right&&nums[left]==nums[left-1]) ++left;while(left<right&&nums[right]==nums[right+1]) --right;}}//去重++j;while(j<n&&nums[j]==nums[j-1]) ++j;}//去重++i;while(i<n&&nums[i]==nums[i-1]) ++i;}return ret;}
};

九、总结

常见的双指针有三种形式:前后指针、对撞指针、快慢指针

1、前后指针:用于顺序结构,一般是两个指针同方向,cur指针用来遍历数组,des指针将数组进行区域划分。(如1、2题)

       注意事项:如果是从前往后遍历,要注意dst不能走得太快,否则cur还没遍历到一些数就会被覆盖掉,必要时候可以根据情况从后往前遍历。

2、快慢指针:其基本思想就是使⽤两个移动速度不同的指针在数组或链表等序列结构上移动。
这种⽅法对于处理环形链表或数组⾮常有⽤。(如第3题,以及链表带环的问题)

        注意事项: 其实不单单是环形链表或者是数组,如果我们要研究的问题出现循环往复的情况时,均可考虑使⽤快慢指针的思想。最常用的就是快指针走两步,慢指针走一步。

3、对撞指针:一般用于顺序结构。从两端向中间移动。⼀个指针从最左端开始,另⼀个从最右端开始,然后逐渐往中间逼近。并且常常会用到单调性!!(如4-8题)
        注意事项:对撞指针的终⽌条件⼀般是两个指针相遇或者错开(也可能在循环内部找到结果直接跳出循环)

用双指针策略一般可以比暴力枚举降低一个次方的时间复杂度

     如果后面还有关双指针的经典题目,博主会继续在这篇更新的!!

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

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

相关文章

专升本 C语言笔记-06 常用的3种输入输出函数

1.scanf() 与 printf() 的使用 scanf() 格式化输入数据 格式:scanf("格式控制字符串",参数地址列表) scanf("%d,%d,%d",&a,&b,&c); printf("a %d\n",a); printf("b %d\n",b); printf("c %d\n",c); 注意 注…

ArcGIS模型构建器Pro版_更多花活演示

相比较ArcMap的模型构建器&#xff0c;Pro里最主要的变化就是增加了一组逻辑工具&#xff1a; 逻辑工具用于控制模型中的流程流&#xff0c;它们返回的结果是true或false。 这个结果一般用于 if-else 分支逻辑&#xff0c;例如&#xff1a;如果某字段存在的时候&#xff0c;执…

【vue baidu-map】实现百度地图展示基地,鼠标悬浮标注点展示详细信息

实现效果如下&#xff1a; 自用代码记录 <template><div class"map" style"position: relative;"><baidu-mapid"bjmap":scroll-wheel-zoom"true":auto-resize"true"ready"handler"><bm-mar…

力扣78. 子集

Problem: 78. 子集 文章目录 题目描述思路及解法复杂度Code 题目描述 思路及解法 1.定义一维数组track用于记录决策路径&#xff0c;二维数组res用于存储所有的子集&#xff1b; 2.决策阶段&#xff1a;从0阶段起来&#xff08;0阶段决策路径中为空集&#xff09;&#xff0c;每…

力扣每日一题 卖木头块 线性DP

Problem: 2312. 卖木头块 文章目录 思路复杂度Code 思路 &#x1f468;‍&#x1f3eb; 灵神题解 复杂度 时间复杂度: O ( n m ( m n ) ) O(nm(mn)) O(nm(mn)) 空间复杂度: O ( n m ) O(nm) O(nm) Code class Solution {public long sellingWood(int n, int m, int…

“城市绿肺诊断:集成GIS、RS、VORS模型、CCDM模型、geodetecto、GWR模型技术深入解析生态系统与城镇化协调发展“

基于GIS、RS、VORS模型、CCDM模型、geodetecto、GWR模型集成的生态系统健康的耦合协调分析 城市群是一国经济发展水平的象征&#xff0c;也是一国经济发展到一定阶段的标志&#xff0c;我国城市群建设体量不断增加&#xff0c;将成为全球经济的核心&#xff0c;中国城市群的建…

除了「au revoir」,「再见」还能怎么说?柯桥成人学外语来银泰附近

1. Je dois y alle#15857575376r I have to go there Y there&#xff0c;意思是“我要走了”。 例如&#xff0c;”Moi, je dois y aller.” 对不起&#xff0c;我该走了。 如果你和同伴都要离开&#xff0c;那就可以说"On y va"&#xff0c;它相当于英语里…

应用程序开发教学:医保购药系统源码搭建实战

医保购药系统作为医疗服务的重要组成部分&#xff0c;其开发不仅能够为患者提供更加便捷的购药服务&#xff0c;还能够提高医疗机构的管理效率。接下来&#xff0c;小编将为您讲解医保购药系统的源码搭建过程&#xff0c;介绍应用程序开发的基本步骤和技巧。 一、系统设计 我…

一键批量瘦身:高效图片像素压缩,解放你的生产力

在快节奏的工作环境中&#xff0c;我们时常需要处理大量的图片文件。这些图片不仅占据了大量的存储空间&#xff0c;而且在传输和加载时也会耗费大量的时间。如何高效、批量地处理这些图片&#xff0c;成为了提升工作效率的关键。今天&#xff0c;我要为大家介绍一款能够一键批…

maven私服搭建详细教程

1、为什么需要私服 如果在公司中多个项目模块中的的公共类用的都是一样的&#xff0c;那么不可能将这些一样的代码写两遍。所以将其中一个项目中的代码打包成私服&#xff0c;然后在另外一个模块中去进行引用。 除此之外&#xff0c;如果大公司中开发人员较多&#xff0c;大家同…

C语言葵花宝典之——文件操作

前言&#xff1a; 在之前的学习中&#xff0c;我们所写的C语言程序总是在运行结束之后&#xff0c;就会自动销毁&#xff0c;那如果我们想将一个结果进行长期存储应该如何操作呢&#xff1f;这时候就需要我们用文件来操作。 目录 1、什么是文件&#xff1f; 1.1 程序文件 1.2…

《ARM汇编与逆向工程 蓝狐卷 基础知识》

大家好&#xff0c;我是爱编程的喵喵。双985硕士毕业&#xff0c;现担任全栈工程师一职&#xff0c;热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。…