首页 > 编程语言 >【进阶算法】双指针

【进阶算法】双指针

时间:2023-11-12 17:00:39浏览次数:35  
标签:slow 进阶 nums 元素 fast 算法 数组 指针

双指针是一种应用很广泛且基础的编程技巧,双指针中的“指针”是指索引、游标。

一、双指针思想

双指针是指在遍历对象的过程中,不是普通的使用单个指针进行访问,而是使用两个指针进行遍历,从而达到相应的目的。

最常见的双指针算法有两种:

  1. 在同一个序列中,用两个指针维护两个位置,或两个位置包含的区间;
  2. 在两个序列里边,两个指针指向不同的序列,来维护某种次序。

二、常见算法模型

按照指针的移动方向,双指针分为同向双指针、异向双指针。

同向双指针,也称快慢指针(两个指针一快一慢);异向双指针,分为对撞指针(从两边向中间移动)、背向指针(从中间向两边移动)。

 

2.1 快慢指针

两个指针,初始在同一位置,然后向相同方向移动,一个移动速度快,一个移动速度慢。

适用场景:查找链表中间节点、链表是否包含环、原地修改数组。

 

示例:LeetCode 876.【链表的中间结点】

给你单链表的头结点 head ,请你找出并返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。如下图所示,链表有 5 个节点,返回第 3 个节点;链表有 6 个节点,返回第 4 个节点。

我们可以通过遍历 2 次链表来找到中间节点,第 1 次遍历获取链表长度 len,第 2 次遍历到 len/2 的位置。但是,使用快慢指针只需要遍历一次就可以解决,明显运行效率可以得到提升。

/**
 * 获取单链表中间节点
 *
 * @param head 单链表头节点
 * @return 中间节点
 */
public ListNode middleNode(ListNode head) {
    ListNode fast = head;
    ListNode slow = head;
    while (fast != null && fast.next != null) {
        fast = fast.next.next;
        slow = slow.next;
    }
    return slow;
}

 

示例:LeetCode 26.【删除有序数组中的重复项】

给你一个非严格递增排列的数组 nums ,请你原地删除重复出现的元素,使每个元素只出现一次 ,返回删除后数组的新长度。元素的相对顺序应该保持 一致 。然后返回 nums 中唯一元素的个数。

考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过:

  • 更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。
  • 返回 k 。

 

思路:如果不是原地修改的话,可以用一个新数组保存去重之后的元素,返回新数组长度即可。但是原地修改,只能在原始数组上操作,所以,需要考虑使用快慢指针。

让慢指针 slow 走在后面,快指针 fast 走在前面,fast找到一个不重复的元素就赋值给 slow 并让 slow 前进一步。这样,就保证了 nums[0..slow] 都是不重复的元素,当 fast 指针遍历完整个数组 nums 后,nums[0..slow] 就是整个数组去重之后的结果。

 

/**
 * 原地删除数组重复元素
 *
 * @param nums 原始数组
 * @return 不重复元素的数量
 */
public int removeDuplicates(int[] nums) {
    int fast = 1;
    int slow = 0;
    int len = nums.length;
    while (fast < len) {
        // 出现不重复元素
        if (nums[fast] != nums[slow]) {
            slow++;
            // nums[0...slow] 保存不重复元素
            nums[slow] = nums[fast];
        }
        fast++;
    }
    return slow + 1;
}

 

示例:LeetCode 27.【移除元素】

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

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

 

思路:原地修改数组考虑使用快慢指针。

让慢指针 slow 走在后面,快指针 fast 走在前面,fast遇到值为 val 的元素直接跳过,否则就赋值给 slow 并让 slow 前进一步。这样,就保证了 nums[0..slow] 都是不为val的元素,当 fast 指针遍历完整个数组 nums 后,nums[0..slow] 就是需要的结果。

 

/**
 * 移除值为 val 的元素
 *
 * @param nums 原始数组
 * @param val  移除的元素值
 * @return 移除值为 val 的元素后,数组的长度
 */
public int removeElement(int[] nums, int val) {
    int fast = 0;
    int slow = 0;
    int len = nums.length;
    while (fast < len) {
        if (nums[fast] != val) {
            nums[slow] = nums[fast];
            slow++;
        }
        fast++;
    }
    return slow;
}

 

2.2 对撞指针

 

标签:slow,进阶,nums,元素,fast,算法,数组,指针
From: https://www.cnblogs.com/luwei0424/p/17810978.html

相关文章

  • 算法题:跳房子问题(爬楼梯问题进阶) 求解受限制情况下的方案数目
    问题跳房子,规定总共有n个格子,每次可以选择跳1个格子、2个格子或3个格子,但是下一步不能和当前选择的跳跃距离一样,计算总共有多少种跳房子方案。分析这就是经典爬楼梯问题的进阶,仅仅换了个说法,但是比经典的爬楼梯问题难了不少,传统的爬楼梯问题一次可以上1或2个台阶没有连续动作......
  • .Net进阶(5)使用Fody实现 .NET的静态编织
    序言 广义的面向切面编程,有静态编织和动态代理两种形式,它们都可以在某个方法执行前后插入某种处理逻辑。不同的地方在于,前者发生在编译时期间,后者发生在运行时期间。对于.NET而言,最常见的静态编织方案是 PostSharp 和 Mono.Cecil,两者的区别是:一个付费、一个免费。本文介......
  • 历时三年,写的一本数据结构与算法pdf,开源了!
    前言大家好,我是bigsai,很早就在写博客,将文章整理成了一个pdf,并且开源到github上!自己写东西断断续续也不少时间了,也写了不少东西(虽然是偏向小白),这个其实花费的时间还是比较多的,这次的话主要将数据结构与算法中一些文章整理出来,初步整理成一版pdf,先分享给大家。因为在整理pdf方......
  • 【10.0】Go语言基础之指针
    【一】什么是指针指针是—种存储变量内存地址(MemoryAddress)的变量。如上图所示,变量b的值为156,而b的内存地址为0x1040a124。变量α存储了b的地址。我们就称a指向了b。【二】指针的定义【1】指针的语法基础1类型前放*表示指针类型,这个类型的指针,指向......
  • JVM系列-第10章-垃圾回收概述和相关算法-cnblog
    title:JVM系列-第10章-垃圾回收概述和相关算法tags:-JVM-虚拟机categories:-JVM-1.内存与垃圾回收篇keywords:JVM,虚拟机。description:JVM系列-第10章-垃圾回收概述和相关算法。cover:'https://gitee.com/youthlql/randombg/raw/master/logo/jvm.png'ab......
  • 【教3妹学编程-算法题】 在树上执行操作以后得到的最大分数
    3妹:2哥,今日都立冬了,可是天气一点都不冷。2哥 :立冬了,晚上要不要一起出去吃饺子?......
  • 【教3妹学编程-算法题】765. 情侣牵手
    3妹:2哥2哥,你看到新闻了吗?襄阳健桥医院院长公然“贩卖出生证明”,真是太胆大包天了吧。2哥 :我也看到新闻了,7人被采取刑事强制措施。就应该好好查查他们,一查到底!3妹:真的是太可气了,白衣天使,本应该治病救人,没想到竟然能干出这种事情。2哥 :哎,真相会迟到,但是不会缺席。幸亏好很......
  • C语言之指针(下)
    指针数组与多级指针指针数组由于指针本身也是变量,所以一组同类指针也可以像其它变量一样形成一个数组。如果一个数组的元素均为某一类型的指针,则称该数组为指针数组。语法如下:类型名*数组名[数组长度];char*string[10];案例:编写一个函数,用二分法查找某一个城市名在城市表中是否......
  • 图有关算法题
    图的结构//严蔚敏版数据结构//邻接表存储结构typedefstructArcNode{intadjvex;//该弧所指向的顶点的位置structArcNode*nextarc;//下一个边结点}ArcNode;typedefstructVNode{VertexTypedata;//顶点信息structArcNode*firstarc;//第一个邻接点......
  • Android程序员自救进阶指南
    前言今天摸鱼的时候看到有人36岁在深圳开起了出租车的新闻,而且对方毕业于华南师范大学,曾在大厂当过主管,因为疫情而毕业,至今2年都没能回到主业,因为上有父母,下有孩子,需要养家糊口,不愿跑美团,认为没面子,所以开起了出租车。这话不得不再次刷新了我的三观,原来开出租车还能瞧不起跑外卖的......