算法通关村第三关——双指针的妙用

news2024/11/25 13:23:52

双指针思想

快慢指针

        所谓的双指针其实就是两个变量。双指针思想简单好用,在处理数组、字符串等场景下很常见。看个例子,从下面序列中删除重复元素[1,2,2,2,3,3,3,5,5,7,8],重复元素只保留一个。删除之后的结果应该为[1,2,3,5,7,8]。我们可以在删除第一个2时将将其后面的元素整体向前移动一次,删除第二个2时再将其后的元素整体向前移动一次,处理后面的3和5都一样的情况,这就导致我们需要执行5次大量移动才能完成,效率太低。如果使用双指针可以方便的解决这个问题,如图:

image.png

        首先,定义两个指针slow、fast。slow表示当前位置之前的元素都是不重复的,而fast则一直向后查找,直到找到与slow 位置不一样的(找到不重复的元素)。找到之后就将slow 向后移动一个位置,并肩arr[fast] 复制给arr[slow],之后fast继续向后找,循环执行。找完之后,slow以及之前的元素就是单一的了。这样就可以使用一轮移动解决问题。

对撞型指针 

        上面这种一个指针在前,一个指针在后的方式也称为快慢指针,有些场景需要从两端向中间轴,这种就称为对撞型指针或者叫相向型指针。很多 题目也会用到

背向型指针

        还有一种比较少见的背向型,就是从中间向两边走。这三种类型其实非常简单看的只是两个指针是一起向前走 (相亲相爱一起走),还是从两头向中间走 (冲破干难万险来爱你),还是从中间向两头走 (缘分已尽,就此拜拜)。 

删除元素专题 

原地移除所有数值等于val的元素

题目

         给你一个数组nums 和一个值 val ,你需要原地移除所有数字相等的val的元素,并返回移除后数组的新长度。

要求;

        不要使用额外的数组空间,你必须仅使用O(1) 额外空间 并原地修改输入数组。元素的顺序可以改变,你不需要考虑数组汇总超出新长度后面的元素

例子

        输入: nums = [3,2,2,3] , val = 3

        输出:2

        输入:nums=[0,1,2,2,3,0,4,2] , val = 2

        输出:5

关键点

        在删除的时候,从删除位置开始的所有元素都要向前移动,所以这题的关键是如何有很多值为val的元素的时候,避免反复向前移动。 

方法一、快慢指针

思想

        整体思想就是快慢指针。

        定义两个指针slow和fast,初始值都是0.

        slow之前的位置都是有效部分,fast表示当前要访问的元素 

        以fast为遍历变量,数组遍历的时候,fast不断向后移动:

                如果nums[fast] 的值不为val ,则将其移动到nums[slow++]处

                如果nums[fast] 的值为val,则fast继续向前移动,slow先等待。

        图示:

image.png

        这样一来,前半部分是有效的,后半部分是无效的 

代码实现
    /**
     * 给你一个数组nums 和一个值 val ,你需要原地移除所有数字相等的val的元素,并返回移除后数组的新长度
     * 要求:
     *  不要使用额外的数组空间,你必须仅使用O(1) 额外空间 并原地修改输入数组。元素的顺序可以改变,你不需要考虑数组汇总超出新长度后面的元素
     * @param nums 给定的数组
     * @param val 要删除的值
     * @return 删除数组元素后的新长度
     */
    public static int removeElements(int [] nums,int val){
        // slow 表示有效的下标(未被删除的下标)
        int slow = 0;
        for (int fast = 0; fast < nums.length; fast++) {
            if (nums[fast] != val){
                nums[slow] = nums[fast];
                // 3  2  2  3
                // 3
                // nums[0] = num[1]
                // nums[1] = num[2]
                slow++;
            }
        }
        return slow;
    }

方法二、对撞双指针

        对撞指针,也叫交换移除。核心思想是:从右侧找到不是val的值    来顶替(通过交换、覆盖的方式) 左侧是val的值(如果右侧找到为val的值,就将其忽略,直接right--跳过),最后返回左侧不是val的值 。

        以nums=[0,1,2,2,3,0,4,2],val = 2 为例:

image.png

        当left == right时,left以及左侧的就是删除指定元素2 后的所有元素了 

实现代码
    public static int getremoveElementsSize(int [] nums , int val ){
        int left;
        int right = nums.length -1 ;
        for (left = 0; left <= right ; ){
            if (nums[left] == val && nums[right] != val){
                int temp = nums[left];
                nums[left] = nums[right];
                nums[right] = temp;
            }

            if (nums[left] != val) {
                left++;
            }

            if (nums[right] == val){
                right -- ;
            }

        }
        return left;
    }

        对撞型双指针的过程与后面要学习的快速排序是一个思路,快速排序要比较很多轮,而这里只执行了一轮, 理解本题将非常有利于后面理解快速排序算法

        另外,我们可以发现快慢型双指针留下的元素顺序与原始序列中的是一致的,而在对撞型中元素的顺序和原来的可能不一样了。 

删除有效数组中的重复项

题目

        给你一个 有序 数组 nums ,请你原地删除重复出现的元素,使每个元素只出现一次,返回删除后数组的新长度。

要求:

        不要使用额外的数组空间,你不需要在原地修改输入数组 并在使用O(1)额外空间的条件下完成

代码实现
    /**
     * 给你一个   有序   数组 nums ,请你原地删除重复出现的元素,使每个元素只出现一次,返回删除后数组的新长度。
     * 要求:
     *      不要使用额外的数组空间,你不需要在原地修改输入数组  并在使用O(1)额外空间的条件下完成
     * @param nums  有序数组
     * @return 数组新长度
     */
    public static  int removeCommonElements(int [] nums){
        // slow 表示可以放入新元素的位置(下标),元素为0的不管
        int slow = 1;
        // 循环起到了快指针的作用
        for (int fast = 1 ; fast < nums.length ; fast ++){
            if (nums[fast] != nums[slow -1]){
                nums[slow] = nums[fast];
                slow++;
            }
        }
        return slow;
    }
 

 

 

 

 

 

 

 

 

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

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

相关文章

小程序开发事件系统设计指引

我们在小程序开发中可能会时常听到事件系统这个词&#xff0c;但却对其背后的技术可能不是非常的理解&#xff0c;今天就准备通过一些实际案例的演示为大家进行解释和说明。 什么是事件&#xff1f; 微信小程序官方文档中解释说&#xff1a;事件是用于子组件向父组件传递数据…

Python+requests+unittest执行接口自动化测试详情

这篇文章主要介绍了Pythonrequestsunittest执行接口自动化测试详情&#xff0c;文章围绕主题展开详细的内容介绍&#xff0c;具有一定的参考价值&#xff0c;需要的朋友可以参考一下 1、安装requests、xlrd、json、unittest库 <1>pip 命令安装&#xff1a; pip install …

【Web 表单】与用户数据打交道-1(mdn笔记)

0. Web 表单指南 我们将介绍 Web 表单的各个方面&#xff1a;HTML 结构、样式、验证表单数据&#xff0c;以及提交数据到服务器。 基本指南 你的第一个表单 第一次创建 HTML 表单的经验&#xff0c;包括设计一个简单表单、使用正确的 HTML 元素实现它、通过 CSS 添加一些非常简…

【图论】无向图连通性(tarjan算法)

割边&#xff1a;dfn[u]<low[v] 割点&#xff1a;dfn[u]<low[v] (若为根节点&#xff0c;要有两个v这样的点) 一.知识点&#xff1a; 1.连通&#xff1a; 在图论中&#xff0c;连通性是指一个无向图中的任意两个顶点之间存在路径。如果对于图中的任意两个顶点 u 和 v&…

问道管理:券商板块再度活跃,西南证券3连板,太平洋6天5板

券商板块1日再度拉升&#xff0c;到发稿&#xff0c;财达证券、太平洋、西南证券涨停&#xff0c;首创证券、第一创业涨超5%。 值得注意的是&#xff0c;太平洋近6日已斩获5个涨停板。公司昨日晚间再次发布危险提示称&#xff0c;近日股票价格波动较大&#xff0c;特别提示广大…

分布式异步任务处理组件(四)

基于zookeeper的HA集群设计思路-- 各个节点都可以消费任务&#xff0c;但是由主节点来投票&#xff1b;主节点通过注册zookeeper的临时节点来选举--主节点需要同步从节点的信息正常工作机制--各个节点&#xff08;包括主节点本身&#xff09;在执行任务之前询问主节点&#xf…

2023最新版Nessus10.5+Awvs15.2+Routersploit+Kali

前言&#xff0c;为了方便大家使用&#xff0c;我们将AWVS、Nessus以及Routersploit集成在kali里面&#xff0c;开机即可享用。非常之方便&#xff0c;详情见下文。 0x01. AWVS AWVS是一款自动化的web漏洞扫描工具。能够发现比较常见的web漏洞&#xff0c;例如跨站脚本攻击&am…

【Mysql】group语句删除重复数据只保留一条

【Mysql】group语句删除重复数据只保留一条 【一】案例分析 假如在数据初始化的时候&#xff0c;insert脚本执行了两次&#xff0c;导致表里的数据都是重复的&#xff08;没有设置唯一键&#xff09;。这个时候再加上mybatis-plus的selectOne方法&#xff0c;就会出现报错。因…

Java阻塞队列

什么阻塞队列 阻塞队列&#xff08;BlockingQueue&#xff09;是一个支持两个附加操作的队列。这两个附加的操作支持阻塞的插入和移除方法。 支持阻塞的插入方法&#xff1a;意思是当队列满时&#xff0c;队列会阻塞插入元素的线程&#xff0c;直到队列不满。支持阻塞的移除方…

高并发编程-2. 并发级别

此文章为笔记&#xff0c;为阅读其他文章的感受、补充、记录、练习、汇总&#xff0c;非原创&#xff0c;感谢每个知识分享者。 原文 文章目录 阻塞无饥饿(Starvation-Free)无障碍(Obstruction-Free)无锁(Lock-Free)无等待 由于临界区的存在&#xff0c;多线程之间的并发必须受…

PCIE上位机用什么工具?

可以了解一下神电测控出器的My FPGA开发套件&#xff0c;它可以用来开发FPGA板卡与上位机之间PCIE通信&#xff0c;而且就是用LabVIEW FPGA开发。它使用的是Xillybus PCIe IP核&#xff0c;神电将其封装成了在 LabVIEW FPGA 下的 PCIe CLIP 组件&#xff0c;可以方便的使用。而…

2023年最新前端学习路线【超详细版】

第一个月、HTMLCSS 第1周安排&#xff1a; 是了解前端入门的第一步&#xff0c;要学会IDE插件安装和使用&#xff0c;掌握H5语法和基础标签的应用&#xff0c;学完本周可以进行简单的页面搭建。 1、了解前端行业发展2、了解HTML5对于网页的意义3、学习常用标签/属性&#xf…

流控平台Sentinel搭建和接入教程

流量控制和限流是大型系统必不可少的组成部分&#xff0c;Sentinel是Alibaba提供的一款特别好用的专业工具&#xff0c;属于那种看起来很牛&#xff0c;用起来也很牛的工具&#xff0c;下面记录一下接入的过程。 一&#xff0c;搭建平台 1&#xff0c;下载jar包 地址&#x…

组件(lvs,keeplive,orm,mysql,分布式事务)

lvs LVS 已经集成到Linux内核系统中&#xff0c;ipvsadm 是 LVS 的命令行管理工具。 目前有三种 IP 负载均衡技术&#xff08; VS/NAT 网络地址转换 、VS/TUN IP 隧道技术实现虚拟服务器 和 VS/DR 直接路由&#xff09;&#xff1b; 八种调度算法&#xff1a;轮询 …

解决ComposerStaticInit类重复加载问题

Tp5中composer安装phpoffice后报错 Cannot declare class Composer\Autoload\ComposerStaticInit6c9266e89aa536667bf36f59ad8e6e6b, because the name is already in use 错误原因: 使用ThinkPHP5框架的项目&#xff0c;在引用某些包的时候&#xff0c;可能会通过其它包&…

java判断字符串是否和空字符串(““)相等、是否和空引用(null)相等,比较顺序不同导致出现死代码(Dead code)

我在用Java实现需求的时候&#xff0c;用到了字符串跟空字符串&#xff08;“”&#xff09;比较&#xff0c;跟空引用null比较&#xff0c;两个比较语句的顺序不同&#xff0c;一个顺序出现了死代码&#xff08;Dead code&#xff09;。 下面这个代码片段&#xff0c;字符串li…

【Rust 日报】2023-07-30 Lemmy v0.18.3发布

Lemmy v0.18.3发布 Lemmy 与 Reddit、Lobste.rs 或 Hacker News 等网站类似&#xff1a;你可以订阅你感兴趣的论坛&#xff0c;发布链接和讨论&#xff0c;然后进行投票或评论。但在幕后&#xff0c;Lemmy 和他们不同 —— 任何人都可以很容易地运行一个服务器&#xff0c;所有…

数字化转型才是王道!零售行业的关键五大指标都在这里了,快收藏

新零售是指结合线上和线下的销售模式&#xff0c;利用数字化技术和数据分析手段&#xff0c;通过线上平台吸引消费者&#xff0c;在线下店铺提供更加个性化和便捷的购物体验。 新零售不再将线上和线下视为两个独立的销售渠道&#xff0c;而是将其整合为一个完整的销售生态系统…

RabbitMQ 教程 | 第4章 RabbitMQ 进阶

&#x1f468;&#x1f3fb;‍&#x1f4bb; 热爱摄影的程序员 &#x1f468;&#x1f3fb;‍&#x1f3a8; 喜欢编码的设计师 &#x1f9d5;&#x1f3fb; 擅长设计的剪辑师 &#x1f9d1;&#x1f3fb;‍&#x1f3eb; 一位高冷无情的编码爱好者 大家好&#xff0c;我是 DevO…

Navicat for Mysql8.xx 字段注释中文乱码解决方

问题摘要&#xff1a; Navicat 中表描述中文均正常&#xff0c;只有字段注释中文乱码&#xff0c;原因是系统本身编码&#xff08;命令行chcp&#xff09;中为936&#xff08;GBK&#xff09;而不是65001&#xff08;UTF8)造成的 使用场景&#xff1a; Navicat for MySQL&am…