算法——双指针

一、背景知识 

  • 双指针(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>>();
        // 枚举 a
        for (int first = 0; first < n; ++first) {
            // 需要和上一次枚举的数不相同
            if (first > 0 && nums[first] == nums[first - 1]) {
                continue;
            }
            // c 对应的指针初始指向数组的最右端
            int third = n - 1;
            int target = -nums[first];
            // 枚举 b
            for (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;
            }
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

盘点35个Python书籍Python爱好者不容错过

盘点35个Python书籍Python爱好者不容错过 学习知识费力气&#xff0c;收集整理更不易。 知识付费甚欢喜&#xff0c;为咱码农谋福利。 链接&#xff1a;https://pan.baidu.com/s/1uf-MXZc9aC7y3Qju6VnCYw?pwd8888 提取码&#xff1a;8888 书籍名称&#xff1a; Django教…

效率提升利器:Automa插件的实用指南

Automa是一个chrome扩展&#xff0c;通过拖拽0代码实现工作流&#xff0c;模拟网页的各种点击、表单填写等操作&#xff0c;使用时点击插件脚本一键执行&#xff0c;或者设置定时执行&#xff0c;从而简化我们的工作。 功能介绍 官方文档地址&#xff1a;Getting started | Au…

Altium Designer学习笔记2

原理图的绘制 需要掌握的是系统自带原理图库元件的添加。

HR问:有没有免费的人才测评工具?

人才测评工具分为两种&#xff0c;一种是测评量表&#xff0c;一种是操作量表的工具&#xff0c;在线测评的方式没有普及之前&#xff0c;很多朋友都习惯把测评量表&#xff08;测评试题&#xff09;称为测评工具&#xff0c;其实我认为量表就是量表&#xff0c;而试试量表测评…

全国的科技创新情况数据分享,涵盖2020-2022年三年情况

随着国家对科技创新的重视和大力支持&#xff0c;全国的科技创新情况越来越受到关注。 我们根据中国城市统计年鉴的这方面指标&#xff0c;分析汇总得出全国科技创新情况数据&#xff0c;需要说明的是&#xff0c;由于统计年鉴指标调整&#xff0c;每一年的数据并非字段相同&a…

隐私计算迎来千亿级风口,一文讲清它的技术理论基础

一、安全多方计算 在讨论安全多方计算(下文使用 MPC) 之前&#xff0c;我们先讨论安全多方计算的设定&#xff0c;在MPC 的所有参与者中&#xff0c;某些参与者可能会被一个敌手 (攻击者) 控制&#xff0c;在敌手控制下的参与者被称为被腐化方&#xff0c;它在协议执行过程中会…

算法(圆的定义和相关术语)

无向图的度 图中每一个顶点的度定义为以该项点为一个端点的边的数目 #include <cstdio>const int MAXN 100;int degree[MAXN] { 0 };int main() {int n, m, u, v;scanf("%d%d", &n, &m);//在输出边度的时候就已经表示度的数目了&#xff0c;所以用一…

Atlassian发布最新补贴政策,Jira/Confluence迁移上云最低可至零成本

到2024年2月15日&#xff0c;Atlassian将不再提供对Jira、Confluence、Jira Service Management等Server版产品的支持。 近期&#xff0c;Atlassian推出了一项针对云产品的特殊优惠。现在从Server版迁移到云版&#xff0c;您能享受到高额补贴&#xff0c;甚至成本低至零元。立…

vue中data属性为什么是一个函数?

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;Vue篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来vue篇专栏内容:vue-data属性 目录 为什么data属性是一个函数而不是一个对象&#xff1f; 一、实例和组件定义dat…

Servlet---API详解

文章目录 HttpServlet基础方法doXXX方法Servlet的生命周期 HttpServletRequest获取请求中的信息获取请求传递的参数获取 query string 里的数据获取form表单里的数据获取JSON里的数据如何解析JSON格式获取数据返回数据 HttpServletResponse设置响应的Header设置不同的状态码设置…

深入探讨软件测试技术:方法、工具与最佳实践

&#x1f482; 个人网站:【 海拥】【神级代码资源网站】【办公神器】&#x1f91f; 基于Web端打造的&#xff1a;&#x1f449;轻量化工具创作平台&#x1f485; 想寻找共同学习交流的小伙伴&#xff0c;请点击【全栈技术交流群】 引言 软件测试是软件开发生命周期中至关重要的…

【操作系统】文件系统之文件共享与文件保护

文章目录 文件共享硬链接软链接 文件保护口令保护加密保护访问控制 文件共享 为了实现文件的共享&#xff0c;引入了“计数器”字段&#xff0c;当一个文件每被一个用户所共享&#xff0c;那么计数器就加一。如果一个用户删除文件&#xff0c;计数器相应的减一。如果计数器为0…

威视佰科荣获:2023年“AI天马”高成长性企业

11月14日下午&#xff0c;2023年度“AI天马”认定评审会顺利召开。落实《深圳经济人工智能产业促进条例》&#xff0c;加快推进智能机器人、智能传感器、智能网联汽车、智能终端、脑科学和类脑智能等人工智能相关产业发展&#xff0c;加速AI产业化和产业AI化进程&#xff0c;持…

Redis篇---第十二篇

系列文章目录 文章目录 系列文章目录前言一、Memcache与Redis的区别都有哪些?二、单线程的redis为什么这么快三、redis的数据类型,以及每种数据类型的使用场景前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇…

BGP笔记实验

IGP(Interior Gateway Protocol)——内部网关协议 OSPF RIP IS-IS IGRP EIGRP EGP(External Gateway Protocol)——外部网关协议 EGP BGP——边界网关协议 AS——自治系统 由单一组织or机构独立维护的网络设备&网络资源的集合 网络范围太大 自治 AS号 为了区分不同…

66从零开始学Java之集合中的Collection体系

作者&#xff1a;孙玉昌&#xff0c;昵称【一一哥】&#xff0c;另外【壹壹哥】也是我哦 千锋教育高级教研员、CSDN博客专家、万粉博主、阿里云专家博主、掘金优质作者 前言 截止到今天&#xff0c;我们《从零开始学Java系列》的文章已经要到一个新的阶段了。在此之前&#xf…

每天分享五款工具,让大家工作生活更顺心

​ 快乐不是在于拥有什么,而在于我们和别人分享什么。每天分享五款工具&#xff0c;让大家工作办公更顺心就是我最大的快乐。 1.沙盒软件——Sandboxie ​ Sandboxie是一款可以在沙盒中运行程序的软件&#xff0c;它可以保护用户的系统和数据免受恶意软件、病毒和其他威胁的影…

pytorch下载离线包的网址

下载地址&#xff1a;https://download.pytorch.org/whl/torch_stable.html 安装GPU版本需要安装&#xff1a;torch、torchvision、 注意版本需要对应上 格式&#xff1a;适用cuda版本&#xff0c;torch版本 或者 orchvision版本&#xff0c;cp38就是适用python 3.8版本 下…

亚马逊车灯外贸出口CE认证标准办理解析

车灯是车辆夜间行驶在道路照明的工具&#xff0c;也是发出各种车辆行驶信号的提示工具。车灯一般分为前照灯、尾灯、转向灯等。车灯出口欧盟需要办理CE认证。 CE认证是欧盟对进入欧洲市场的产品强制性的认证标志&#xff0c;是指符合欧盟安全、健康、环境保护等标准和要求的产…

运动装备经营小程序商城效果如何

运动装备可包含服装、帐篷、渔具、箱包鞋帽等&#xff0c;对喜欢外出的人来说&#xff0c;靠谱的装备是关键&#xff0c;往往更容易选择品牌和信得过的商家。 而对商家来说&#xff0c;如何打造品牌提升卖货经营效率和提升营收是重中之重&#xff1b;互联网时代需要商家拓展线…