算法——双指针

一、背景知识 

  • 双指针(Two Pointers):指的是在遍历元素的过程中,不是使用单个指针进行访问,而是使用两个指针进行访问,从而达到相应的目的。
  • 对撞时针
    • 两个指针方向相反
    • 对撞指针一般用来解决有序数组或者字符串问题
  • 快慢指针:
    • 两个指针方向相同,速度不同。移动快的指针被称为 「快指针(fast)」,移动慢的指针被称为「慢指针(slow)」
    • 快慢指针一般用于处理数组中的移动、删除元素问题,或者链表中的判断是否有环、长度问题。
  • 分离双指针:
    • 两个指针分别属于不同的数组 / 链表
    • 分离双指针一般用于处理有序数组合并,求交集、并集问题。
  • 滑动窗口法:

    • 两个指针,一前一后组成滑动窗口,并计算滑动窗口中的元素的问题。一般是右端向右扩充,达到停止条件后右端不动,左端向右端逼近,逼近达到停止条件后,左端不动,右端继续扩充。

    • 滑动窗口法一般用于处理字符串匹配问题和子数组问题
  • 时间复杂度O(n)

二、例题

总结:

  • 要移动多个指针的情况可以分解成双指针的情况(1+n)
  • 关键是什么条件下移动哪个指针,分开思考,一起走就容易乱 

 1、移动零(快慢指针)

突破点:右指针是贴着左指针开始往右移的,不是从数组右端往左移,因为那样会搅乱数组元素的相对顺序 

class Solution {public void moveZeroes(int[] nums) {int l=0;//左指针int r=0;//右指针int count=0;//计算0的个数while(r<nums.length){if(nums[r]!=0 && nums[l]==0){//找到0,交换后,左右指针都往右移nums[l]=nums[r];nums[r]=0;count++;l++;}if(nums[l]!=0){//没找到0,左右指针都往右移l++;}//前两种情况都有r++; 所以把它提到外面,大家都能用r++;//如果只有左指针找到0,右指针继续往右移}}
}

 代码优化:封装方法

class Solution {public void moveZeroes(int[] nums) {int n = nums.length, left = 0, right = 0;while (right < n) {if (nums[right] != 0) {swap(nums, left, right);left++;}right++;}}public void swap(int[] nums, int left, int right) {int temp = nums[left];nums[left] = nums[right];nums[right] = temp;}
}

2、盛最多水的容器(对撞指针)

突破点:不是同时移动两个指针,而是只移动较小的那个,因为较小的值改变会影响整体面积 

public class Solution {public int maxArea(int[] height) {int l = 0, r = height.length - 1;//左右指针分别指向数组的头尾int ans = 0;//维护一个最大值while (l < r) {int area = Math.min(height[l], height[r]) * (r - l);//当前面积,不一定是最大值ans = Math.max(ans, area);//移动数字较小的那个指针,整体面积才会发生变化 if (height[l] <= height[r]) {++l;}else {--r;}}return ans;}
}

3、三数之和(对撞指针)

突破点:三个指针的相对方位不会改变,一左一中一右,
        它们也不会走对方走过的路,因为它们三个实际上是相同的
        如果改变了方位,就会出现重复的三元组 

class Solution {public List<List<Integer>> threeSum(int[] nums) {int n = nums.length;Arrays.sort(nums);List<List<Integer>> ans = new ArrayList<List<Integer>>();// 枚举 afor (int first = 0; first < n; ++first) {// 需要和上一次枚举的数不相同if (first > 0 && nums[first] == nums[first - 1]) {continue;}// c 对应的指针初始指向数组的最右端int third = n - 1;int target = -nums[first];// 枚举 bfor (int second = first + 1; second < n; ++second) {// 需要和上一次枚举的数不相同if (second > first + 1 && nums[second] == nums[second - 1]) {continue;}// 需要保证 b 的指针在 c 的指针的左侧// 因为当b走到c的右边时,相当于原来的c,会有重复的三元组产生while (second < third && nums[second] + nums[third] > target) {//b和c之和大于target,b是往右走值是增大的,所以要移动c指针往左走--third;}// 如果指针重合,随着 b 后续的增加// 就不会有满足 a+b+c=0 并且 b<c 的 c 了,可以退出循环if (second == third) {break;}//找到了 if (nums[second] + nums[third] == target) {List<Integer> list = new ArrayList<Integer>();list.add(nums[first]);list.add(nums[second]);list.add(nums[third]);ans.add(list);}}}return ans;}
}

4、接雨水(对撞指针)

突破点:是从两边向中间逼近,而非从左到右 

class Solution {public int trap(int[] height) {int ans=0;int left=0,right=height.length-1;//左右指针分别指向数组的头尾端int leftMax=0,rightMax=0;while(left<right){//指针未相撞leftMax=Math.max(leftMax,height[left]);rightMax=Math.max(rightMax,height[right]);if(height[left]<height[right]){ans+=leftMax-height[left];//当前height[left]夹在leftMax和rightMax中间,所以它的存水量受制于最小值++left;//移动最小值,才会改变可存水量}else{ans+=rightMax-height[right];--right;}}}
}

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

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

相关文章

浅谈能源智能管理系统在大学高校中的应用

安科瑞 华楠 摘要&#xff1a;结合深圳南方科技大学能效系统工程设计实例&#xff0c;针对校园中电耗、热量消耗、冷量消耗及水资源消耗数据的采集、传输、分析管理系统&#xff0c;分析了系统中的水、电、气在高校中的能耗分布&#xff0c;并阐述了节能应用方案&#xff0c;可…

Java 编码

编码: 加密: 通过加密算法和密钥进行 也可通过码表进行加密 对称加密: 缺点:可被截获 元数据---加密算法密钥密文 ----> 解密算法密钥元数据 算法:DES(短 56位),AES(长 128位)破解时间加长 非对称加密: 元数据-加密算法加密密钥 密文 --->加密算法解密密钥元数据 …

在终端输入任意的英文字符串,求最后一个单词的长度

实例要求&#xff1a;1、在终端输入任意的英文字符串 s&#xff0c;由若干单词组成&#xff0c;单词前后用一些空格字符隔开&#xff1b;2、返回字符串中 最后一个 单词的长度&#xff1b;3、单词 是指仅由字母组成、不包含任何空格字符的最大子字符串&#xff1b;示例代码&…

C++(模板进阶)

目录 前言&#xff1a; 本章学习目标&#xff1a; 1.非类型模版参数 1.1使用方法 1.2注意事项 1.3 实际引用 2.模版特化 2.1概念 2.2函数模板特化 2.3类模板特化 2.3.1全特化 2.3.2偏特化 3.模版分离编译 ​编辑 3.1失败原因 ​编辑 3.2解决方案 4 总结 前言&…

SQL 中的 MIN 和 MAX 以及常见函数详解及示例演示

SQL MIN() 和 MAX() 函数 SQL中的MIN()函数和MAX()函数用于查找所选列的最小值和最大值&#xff0c;分别。以下是它们的用法和示例&#xff1a; MIN() 函数 MIN()函数返回所选列的最小值。 示例&#xff1a; 查找Products表中的最低价格&#xff1a; SELECT MIN(Price) F…

设计循环队列,解决假溢出问题

什么是假溢出&#xff1f; 当我们使用队列这种基本的数据结构时&#xff0c;很容易发现&#xff0c;随着入队和出队操作的不断进行&#xff0c;队列的数据区域不断地偏向队尾方向移动。当我们的队尾指针指向了队列之外的区域时&#xff0c;我们就不能再进行入队操作了&#xff…

Go 语言函数、参数和返回值详解

函数是一组语句&#xff0c;可以在程序中重复使用。函数不会在页面加载时自动执行。函数将通过调用函数来执行。 创建函数 要创建&#xff08;通常称为声明&#xff09;一个函数&#xff0c;请执行以下操作&#xff1a; 使用 func 关键字。指定函数的名称&#xff0c;后跟括…

打不开clickonce问题解决过程

1.用户电脑user文件夹下有xx和xx.1两个账户,原先安装在xx账户下,后修了电脑原数据保留在xx.1,新创建XX,之后clickonce就打不开了表现为没有反应,,删除注册表和appdata都只能正常安装,但是不能打开,没有任何报错,发现在我的电脑下打开有这样的提示,,在用户电脑上没有 尝试通过修…

电大搜题——让学习变得轻松高效

作为一名现代学者&#xff0c;您一定时刻关注着教育领域的进展和创新。今天&#xff0c;我将向大家介绍一个名为“电大搜题”的神奇工具&#xff0c;它将为您的学习之路带来一场完美的革命。 在快节奏的现代社会中&#xff0c;学习已经成为每个人追求成功的必经之路。然而&…

攻防世界-web-Confusion1

1. 题目描述 打开链接&#xff0c;如图 点击Login和Rigister&#xff0c;都报错 但是有提示 指出了flag所在的位置&#xff0c;题目中直接能获取到的信息暂时就这么些了 2. 思路分析 既然告诉了我们flag文件的位置&#xff0c;那么要读取到这个文件&#xff0c;要么是任意文…

设计模式-创建型模式-工厂方法模式

一、什么是工厂方法模式 工厂模式又称工厂方法模式&#xff0c;是一种创建型设计模式&#xff0c;其在父类中提供一个创建对象的方法&#xff0c; 允许子类决定实例化对象的类型。工厂方法模式是目标是定义一个创建产品对象的工厂接口&#xff0c;将实际创建工作推迟到子类中。…

双流网络论文精读笔记

精读视频&#xff1a;双流网络论文逐段精读【论文精读】_哔哩哔哩_bilibili Two-Stream Convolutional Networks for Action Recognition in Videos 传统的神经网络难以学习到物体的运动信息&#xff0c;双流网络则通过光流将物体运动信息抽取出来再传递给神经网络 给模型提供…