文章目录

  • 一.双指针的概念
  • 二. 双指针的分类及解题步骤
    • (一)同向双指针
      • 1.概念
      • 2.解题步骤
    • (二)反向双指针
      • 1.概念
      • 2.解题步骤
  • 三. 相关例题及其解法
    • (一)leetcode 26 统计不重复的个数(简单)
      • 1.题目
      • 2. 解法及代码
    • (二)leetcode 344 反转字符串(简单)
      • 1.题目
      • 2. 解法及代码
    • (三)leetcode 11 盛水最多的容器(中等)
      • 1.题目
      • 2. 解法及代码
    • (四)leetcode 42 接雨水(困难)
      • 1.题目
      • 2. 解法及代码
    • (五)leetcode 283 移动零(简单)
      • 1.题目
      • 2. 解法及代码
    • (六)leetcode 80. 删除有序数组中的重复项 II(中等)
      • 1.题目
      • 2. 解法及代码

一.双指针的概念

双指针(two pointers)方法,可以用于解决一系列常见的array/vector/string题目。双指针是一种通过两个index pointer操作数组的方法,通过这种方法,可以将数组分成 [0, left), [left, right), [right, array.length) 三部分。使用这种方法时,一定要先明确各个部分的含义。

二. 双指针的分类及解题步骤

(一)同向双指针

1.概念


如上图所示, 同向双指针是指两个index pointer朝着同一个方向移动,但是他们的移动速度不同。其中 [0, i) 的数据代表处理好的数据,[i, j) 中的数据是那些处理过但不需要的数据,[j, array.length) 区间的数据为接下来待处理的数据。

2.解题步骤

1. Initialize two pointers: int left = 0, right = 0;
2. while right < array.length:* If we need array[right], then array[left++] = array[right++]* Otherwise, skip it and move right forward until array[right] is needed

注意:上面的 array[left++] = array[right++] 包括先给左指针所在位置赋值然后再移动两个指针向前移动两个步骤

(二)反向双指针

1.概念


如上图所示,反向双指针中的两个指针反向而行,同样分为三个区间。
其中 [0, i) 和 (j, array.length) 内的数据均为处理好的数据,[i, j] 中的数据待处理。用此方法处理过的数组不会保留原来元素的相对位置。

2.解题步骤

1. Initialize two pointers: int left = 0, right = array.length - 1;
2. while left < right:* Decide what you should do based on the value of array[i] and array[j]* Move at least one pointer forward in its direction

三. 相关例题及其解法

(一)leetcode 26 统计不重复的个数(简单)

1.题目

https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array/

2. 解法及代码

思路:
本题使用同向双指针
1.判空,如果数组为空直接返回0
2.初始化双指针
3. while right < vector.size():a. 第一个位置(left = 0)直接复制过来,并向前移动两个指针b. 如果right的数值和left左边一个位置数值不相等 ,那么就是我们需要的,赋值过来并向前移动两个指针;c. 否则,就向前移动right直到满足a,b
class Solution {public:int removeDuplicates(vector<int>& nums) {if(nums.size() == 0) return 0; //判空int left = 0, right = 0;  // 初始化双指针while(right < nums.size()){if(i == 0 || nums[right] != nums[left - 1]){nums[left++] = nums[right++]; //赋值之后向前移动两个指针}else{right++;}         }return left; //因为复制之后 left++,所以这里的left就是个数}
};

(二)leetcode 344 反转字符串(简单)

1.题目

https://leetcode-cn.com/problems/reverse-string/

2. 解法及代码

思路:
本题使用反向双指针
1.定义双指针
2. while left < right:依次对应交换位置
class Solution {public:void reverseString(vector<char>& s) {int left = 0, right = s.size() - 1;while(left < right){swap(s[left++], s[right--]);//交换位置并相向移动双指针}       }
};

(三)leetcode 11 盛水最多的容器(中等)

1.题目

https://leetcode-cn.com/problems/container-with-most-water/

2. 解法及代码

思路:
本题使用反向双指针
1.定义双指针
2.定义result记录当前最大面积
3. while left < right:a. 计算当前的面积 = left和right中比较低的高度 * 间隔b. 如果当前面积大于之前的最大面积就更新结果c. 移动left和right中比较低的一个指针(下面用反证法证明其合理性)我们令 S1 = 当前面积,a1 = height[left], b1 = height[right], t1 = right - left移动之前的面积: S1 = min(a1, b1)*t1现在假设a1 < b1, 我们向左移动right得到b2和t2在移动之后:t2 < t1如果b2 > a1, S2 = min(a1, b2)*t2 = a1 * t2 < S1;如果b2 <= a1, S2 = min(a1, b2)*t2 = b2 * t2 <= a1 * t2 < s2.所以如果移动比较大的一个,移动之后得到的面积一定小于原来的面积。因此为了得到最大面积,我们要移动比较小的一个。
class Solution {public:int maxArea(vector<int>& height) {int i = 0, j = height.size()-1;int result = 0;while(i<j){// 计算当前的面积 = 比较低的高度 * 间隔int area = min(height[i], height[j])*(j-i);// 更新结果result = max(result, area);// 移动较小的一段(height[i] > height[j]) ? (j--) : (i++);}return result;}
};

(四)leetcode 42 接雨水(困难)

1.题目

https://leetcode-cn.com/problems/trapping-rain-water/

2. 解法及代码

思路:
本题有多解,这里使用反向双指针
1. 判空
2. 定义result记录结果
3. 定义双指针、leftMax(记录left及其左侧的柱子最高高度)、 rightMax(记录right及其左侧的柱子最高高度)
4. while left < right:a. 更新两边最高高度:leftMax = max(leftMax, height[left]);rightMax = max(rightMax, height[right]);b. 比较左右侧当前高度:1) if(height[left] < height[right]), 必有leftMax <= rightMax。此时计算left处接的雨水 = leftMax- height[left],将其加到reslut里面并右移left。2)if(height[left] >= height[right]), 必有leftMax >= rightMax。此时计算right处接的雨水 = rightMax- height[right],将其加到reslut里面并左移right。下面证明if(height[left] < height[right]), 必有leftMax <= rightMax
left右移终止条件是找到一个不小于rightMax的leftMax, 所以当left终止右移的时候此时的height[left]就是leftMax,
所以if(height[left] < height[right]),then leftMax <= height[right] <= rightMax, 故必有 leftMax <= rightMax。
class Solution {public:int trap(vector<int>& height) {int result = 0;int n = height.size();if(n==0) return 0;int left = 0, right = n-1, leftMax = height[0], rightMax = height[n - 1];while(left < right){leftMax = max(leftMax, height[left]);rightMax = max(rightMax, height[right]);if(height[left] < height[right]){result += leftMax - height[left];left++;}else{result += rightMax - height[right];right--;}}return result;}
};

(五)leetcode 283 移动零(简单)

1.题目

https://leetcode-cn.com/problems/move-zeroes/

2. 解法及代码

本题使用同向双指针
1. 初始化同向双指针
2. while right < array.length:* if(array[right]!=0) swap(array[left], array[right]),并且left右移* right右移简言之,只要array[right]!=0,left和right就一起右移。否则,right先右移直到array[right]!=0,然后再和交换array[left],再一起右移。
class Solution {public:void moveZeroes(vector<int>& nums) {int left =0, right = 0;while(right < nums.size()){if(nums[right]){swap(nums[left++], nums[right]);}right++;        }}
};

(六)leetcode 80. 删除有序数组中的重复项 II(中等)

1.题目

https://leetcode-cn.com/problems/remove-duplicates-from-sorted-array-ii/

2. 解法及代码

值得一提,本人下面的代码运行速度击败了leetcode100% C++用户

本题使用同向双指针
1. 初始化同向双指针,不过这里有所不同,我们设定left = 2, right = 2;因为题目要求可以有两个重复项,所以如果长度少于2,无需进行操作,直接返回数组长度即可;
2. 当长度大于2,的时候,前两项不用管,从第三项开始,while right < array.length:* if(nums[right] != nums[left-2]), nums[left] = nums[right]并且右移left* 否则右移right
class Solution {public:int removeDuplicates(vector<int>& nums) {int n = nums.size();int left = 2 ,right = 2;    while(right < n){if((nums[right] != nums[left-2])){nums[left++] = nums[right];}right++;}return min(left, n); // 长度小于2的时候无需操作,直接返回长度n}
};

【C++刷LeetCode套路1】Array题型: 双指针Two Pointers套路相关推荐

  1. 手把手带你刷Leetcode力扣 学习总结

    文章目录 1. 总体规划 2. 算法复杂度 2.1 时间复杂度 2.2 空间复杂度 3. 数据结构 3.1 数组[Array] 3.1.1 Python常用操作 3.1.2 Java常用操作 3.1. ...

  2. 吴忠强:刷LeetCode的正确姿势!

    ↑↑↑关注后"星标"Datawhale 每日干货 & 每月组队学习,不错过 Datawhale干货 作者:吴忠强,东北大学,Datawhale成员 写在前面 最近面试中做算 ...

  3. 【前端来刷LeetCode】两数之和与两数相加

    大部分玩前端的小伙伴,在算法上都相对要薄弱些,毕竟调样式.调兼容就够掉头发的了,哪还有多余的头发再去折腾. 确实在前端中需要使用到算法的地方是比较少,但若要往高级方向发展,算法的基本功就非常重要啦.对 ...

  4. 【算法】吴忠强:刷LeetCode的正确姿势!

    作者:吴忠强,东北大学,Datawhale成员 写在前面 最近面试中做算法题,受了打击,和我之前准备的很不一样.这篇文章通过笔试实战经验复盘我在刷LeetCode的一些误区和今后对策,供大家参考备战秋 ...

  5. leetcode 330. Patching Array | 1798. Maximum Number of Consecutive Values You Can Make

    1798. Maximum Number of Consecutive Values You Can Make | 1798. 你能构造出连续值的最大数目 https://leetcode.com/p ...

  6. js splice方法_我用JS刷LeetCode | Day 8

    如有兴趣,微信搜索「九零后重庆崽儿」,我们一起学前端. 删除排序数组中的重复项: 说明:现阶段的解题暂未考虑复杂度问题 首发地址: 我用JS刷LeetCode | Day 8​www.brandhua ...

  7. 刷leetcode习题

    为什么要刷leetcode 面试笔试在leetcode上面抽题. 如何刷leetcode题 我的方法 1.写思路. 平时练leetcode题,先锻炼自己的思维能力,先把自己现阶段可以想到的做法都用注释 ...

  8. 进入到Google之前,一定要学会刷LeetCode!!

    点击上方的终端研发部,右上角选择"设为星标" 每日早9点半,技术文章准时送上 公众号后台回复"学习",获取作者独家秘制精品资料 往期文章 重磅!微软GitHub ...

  9. leetcode怎么用时间刷_大家都是如何刷 LeetCode 的?

    2020年4月更新: 跳槽告一段落,开启新的旅程.不用再爆肝刷题了,但还会做周赛保持手感. TL, DR 太长不看零基础先去学一点"数据结构","算法设计与分析" ...

  10. 刷leetcode是什么样的体验?【转】

    转自:https://www.zhihu.com/question/32322023 刷leetcode是什么样的体验? https://leetcode.com/ 1 条评论 默认排序 按时间排序 ...

最新文章

  1. Ubuntu14.04安装JDK
  2. python3标准库书怎么样_Python3标准库:filecmp比较文件
  3. Input中onbeforepaste的作用
  4. 当Sklearn遇上Plotly,会擦出怎样的火花?
  5. 肝!一款基于 Python 语言的 Linux 资源监视器!
  6. Form表单标签的Enctype属性的编码格类型
  7. rpm部署mysql_使用rpm快速安装部署MySQL5.6以及主从设置
  8. 公众号滑动图代码_如何实现微信公众号文章“滑动查看更多”
  9. 王译潇20162314 第九周作业总结
  10. 用Log Explorer恢复数据的基本操作
  11. oracle10安装提示SID,Oracle重新安装报SID已经存在
  12. 计算机基础知识试题和答案
  13. java手机视频下载_使用JAVA合并哔哩哔哩手机客户端下载的视频
  14. MES智能工厂信息化系统
  15. Python爬虫|Python爬虫入门:请求
  16. 如何提交项目到git
  17. 彩虹六号mute影响服务器笑话,有哪些《彩虹六号》玩家才懂的笑话?
  18. Find Zombies
  19. PHP中数字转为百分位,千分位,万分位。。。
  20. 计算机网络系统拓扑图

热门文章

  1. 用命令打开文件服务器资源管理器,Windows10使用命令参数打开文件资源管理器的方法...
  2. Android字符小写转大写,大写转小写
  3. JS,等额本息,等额本金计算器
  4. 怎样从零开始训练一个AI车手?
  5. EF Core学习之路02
  6. 3dMax 倒角剖面(中式亭子)
  7. C语言程序代码 25 编程实现将任意一个华氏法表示的温度,转换为以摄氏法表示的温度。
  8. Workfine新手入门:数据管理器——条件格式
  9. 微信公众平台开发系列之必备知识
  10. 华为高层谈 35 岁危机,程序员如何破年龄之忧?