力扣82删除排序链表中的重复元素 II:思路分析+代码实现+方法总结(三指针法快慢指针法【双指针】递归法)

news2024/11/23 12:05:44

文章目录

  • 第一部分:题目描述
  • 第二部分:代码实现
    • 2.1 三指针法
    • 2.2 快慢指针法(双指针)
    • 2.3 递归

第一部分:题目描述

🏠 链接:82. 删除排序链表中的重复元素 II - 力扣(LeetCode)

⭐ 难度:中等

image-20230515032300743

第二部分:代码实现

2.1 三指针法

p1 是待删除的上一个节点,每次循环对比 p2、p3 的值。

  • 如果 p2 与 p3 的值重复,那么 p3 继续后移,直到找到与 p2 不重复的节点,p1 指向 p3 完成删除。
  • 如果 p2 与 p3 的值不重复,p1,p2,p3 向后平移一位,继续上面的操作。
  • p2 或 p3 为 null 退出循环。
    • p2 为 null 的情况,比如链表为 1 1 1 null。
p1 p2 p3
s, 1, 1, 1, 2, 3, null

p1 p2    p3
s, 1, 1, 1, 2, 3, null

p1 p2       p3
s, 1, 1, 1, 2, 3, null

p1 p3
s, 2, 3, null

p1 p2 p3
s, 2, 3, null

   p1 p2 p3
s, 2, 3, null

代码:

class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        // 当链表无节点或者只存在头节点,直接返回 null / 头节点
        if (head == null || head.next == null) {
            return head;
        }

        // 设置一个哨兵节点(伪头节点)
        ListNode sentinel = new ListNode(-999, head);
        // p1 指向哨兵节点
        ListNode p1 = sentinel;
        ListNode p2, p3;

        // 设置 p2 为 p1 的下一个节点,p3 为 p1 的下下个节点
        // 如果 此时 p2 或 p3 为空节点说明已遍历完链表,再无重复节点
        while ((p2 = p1.next) != null
                && (p3 = p2.next) != null) {

            // 如果 p2 与 它的下一个节点val值重复,则需要删除当前p2、p3指向的节点以及后面与p2.val相同值的节点
            if (p2.val == p3.val) {

                // 使用 p3 继续向后遍历,直到找到与p2.val不相同值的节点
                while ((p3 = p3.next) != null && p3.val == p2.val) {
                }

                // 此时 p3 指向的节点为不想同值的节点

                // 为了跳过当前 p2 到 p3以前 的节点,可以将p2的上一个节点p1的next 指向p3
                p1.next = p3;

                // 继续下一次循环即可,在循环条件中再次对p2、p3赋值使得p2、p3分别指向p1的下个节点与下下个节点
            } else {
                // 如果 p2 与 它的下一个节点p3的val值不重复,说明链表中不存在与 p2.val 相等的值的节点,
                // 则只需要将 p1、p2、p3后挪一位即可,由于在外层while循环中会对p2、p3赋值,因此在这里只需要对p1后移即可
                p1 = p1.next;
            }
        }

        // 返回真正的头节点
        return sentinel.next;
    }
}

2.2 快慢指针法(双指针)

class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        // 如果链表无节点或者只有一个节点,则返回 null / head
        if (head == null || head.next == null) {
            return head;
        }

        // 设置一个哨兵 sentinel,它的下一个节点为链表头节点 head
        ListNode sentinel = new ListNode(-999, head);
        // 快指针,指向 head
        ListNode fast = head;
        // 慢指针,指向 哨兵
        ListNode slow = sentinel;
        // 记录某个值出现次数
        int count = 0;

        // 使用快指针进行遍历链表
        while (fast != null) {
            // 如果快指针指向的val与慢指针下一个节点的val相等
            if (fast.val == slow.next.val) {
                // 则fast继续向后遍历
                fast = fast.next;
                // 值出现次数 +1
                count++;
            } else {
                // 如果fast遇到与慢指针下一个节点的val不重复的值

                // 判断 慢指针下一个节点的val出现次数即 count 是否为1
                if (count == 1) {
                    // 如果只出现了一次,说明未出现重复的值,则慢指针向后移动一位即可
                    // 此时fast的位置一定是在 slow 的后面一位
                    slow = slow.next;
                } else {
                    // 如果出现了多次,则需要忽略所有与 slow.next.val 具有相等值的节点
                    // 如何忽略呢?只需要更新slow的下一个节点为fast即可
                    slow.next = fast;
                }

                // 遇到了不重复的值,做完了对上一个count的处理后,重新清0进行下一次计算
                count = 0;
            }
        }

        // 当 fast 为空时会退出循环,但并未对count进行后续处理,因此这里还需要处理一下
        // 如果不为1,说明出现了重复节点,如何忽略这些重复节点呢?只需要更新slow的下一个节点为null即可
        if (count != 1) {
            slow.next = null;
        }

        // 返回真正的头节点
        return sentinel.next;
    }
}

2.3 递归

递归函数负责返回:从当前节点(我)开始,完成去重的链表。

  1. 若我与 next 重复,一直找到下一个不重复的节点,以它的返回结果为准。
  2. 若我与 next 不重复,返回我,同时更新 next。
// 链表:1 -> 1 -> 1 -> 2 -> 3

deleteDuplicates(ListNode p = 1) {
    // 找下个不重复的
	deleteDuplicates(ListNode p = 1) {
        deleteDuplicates(ListNode p = 1) {
			deleteDuplicates(ListNode p = 2) {
                2.next=deleteDuplicates(ListNode p = 3) {
					// 只剩一个节点,返回
                    return 3
                }
                return 2
			}
        }
    }
}

代码:

class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        // 边界节点的考虑
        if (head == null || head.next == null) {
            return head;
        }

        // 如果节点的val重复,则删除所有为val的节点
        if (head.val == head.next.val) {
            // 找到下下个节点
            ListNode tmp = head.next.next;
            // 循环遍历后面节点直到找到一个与当前节点val不同的节点
            while (tmp != null && tmp.val == head.val) {
                tmp = tmp.next;
            }

            // 找到的tmp就是与 head 取值不相同的节点
            // 直接舍弃从head开始的这一部分节点,
            // 从 tmp 开始继续递归调用,return返回的节点一般是作为某个节点的下一个节点以达到舍弃的效果
            return deleteDuplicates(tmp);
        }

        // 如果不重复,就更新它的next节点,实际是对后续的节点进行去重操作
        head.next = deleteDuplicates(head.next);
        // 更新next后,返回当前这个不重复的节点即可
        return head;
    }
}

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

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

相关文章

简单快速的在openEuler22.03上部署openGauss2.10

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、安装openEuler1.创建虚拟机2.安装openEuler系统 二、安装openGauss1.设置openGauss2.创建数据库用户并设置权限3.设置防火墙4.远程连接openGauss 总结 前言…

PyQt5桌面应用开发(15):界面动画

本文目录 PyQt5桌面应用系列界面动画PyQt5的动画框架QPropertyAnimationQAnimationGrouppyqtProperty与插值 一个例子代码代码解析 结论 PyQt5桌面应用系列 PyQt5桌面应用开发(1):需求分析 PyQt5桌面应用开发(2)&#…

【手机建站】安卓Termux+cpolar内网穿透,搭建外网可以访问的网站

文章目录 概述1.搭建apache2.安装cpolar内网穿透3.公网访问配置4.固定公网地址5.添加站点 概述 Termux是一个Android终端仿真应用程序,用于在 Android 手机上搭建一个完整的Linux 环境,能够实现Linux下的许多基本操作,不需要root权限Termux就…

电脑格式化后数据恢复软件EasyRecovery16

EasyRecovery是一款由Kroll Ontrack公司开发的专业数据恢复软件,旨在帮助用户从各种数据丢失情况下恢复文件。无论是因为误删除、格式化、分区丢失、系统崩溃还是其他原因导致的数据丢失,EasyRecovery都具有强大的恢复功能。 EasyRecovery提供了多种恢复…

什么是 Git 的 cherry-pick?

官方解析 Git 的 cherry-pick 是一种将指定的提交(commit)应用到当前分支的操作。它可以帮助我们将某个分支上的某次提交复制到另一个分支上,而无需将整个分支合并过来。 通常,我们在使用 Git 进行版本控制时,会在不…

JAVA-Activiti 7与达梦、人大金仓兼容-修改源码包(1)

目录 第一步,下载源码包 第二步,修改源码内容 1.1进行部分源码包修改 1.1.1 在org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl,增加成员变量。 1.1.2 修改org.activiti.engine.impl.cfg.ProcessEngineConfigurationImpl 类的getDefaultDatabase…

UML类图画法及其关系

UML类图画法及其关系 本文主要是介绍 UML类图画法及其关系,方便今后温习!!! 一、类之间的关系汇总 泛化(Generalization)实现(Realization)关联(Association&#xff…

基于springboot+jsp的校园音乐网站系统

该系统能完成的主要功能分为管理员和用户两个用户角色。主要功能包括主页、个人中心、用户管理、校园歌手管理、明星歌手管理、歌曲类别管理、校园歌曲管理、歌曲MV管理、歌手歌曲管理、系统管理等。而用户登入系统也可以对自己的信息以及修改个人资料进行查看等功能。该系统在…

YOLO-NAS C++部署 2023.5.17

这不最近新出了网络,YOLO-NAS,听过性能和速度都不错,而且int8量化后效果也不错。 一、吐槽 但是我打开该项目阅读readme.txt时候,发现这些示例网站一个都打不开! 而且readme.txt很不详细,你想训练自己的模…

设计模式之【访问者模式】,动态双分派的魅力

文章目录 一、什么是访问者模式1、访问者模式的应用场景2、访问者模式的五大角色3、访问者模式的优缺点 二、实例1、访问者模式的通用写法2、宠物喂食实例3、KPI考核案例小总结 三、分派1、什么是分派2、静态分派3、动态分派4、双分派5、访问者模式中的伪动态双分派 四、访问者…

mkv转mp4格式怎么转,5种便捷工具盘点

mkv转mp4格式怎么转?因为当我们下载视频时,通常无法选择格式,这可能会导致下载的视频无法打开。如果下载的是MKV格式,它可以容纳多个音频、视频和字幕流。然而,并非所有播放器都支持MKV格式的视频文件。尽管MKV是常见的…

2D车道线检测算法总结

关于2D车道线检测算法的总结主要分为两类:一类基于语义分割来做,一类基于anchor和关键点来做。还有基于曲线方程来做的,但是落地的话还是上面两种为主。 一、基于语义分割的车道线检测算法 1.LaneNet 论文创新点: 1.将车道线检…

【软考数据库】第十五章 知识产权和标准化

目录 15.1 知识产权概述 15.2 保护期限 15.3 知识产权人的确定 15.4 侵权判断 15.5 标准划分 前言: 笔记来自《文老师软考数据库》教材精讲,精讲视频在b站,某宝都可以找到,个人感觉通俗易懂。 15.1 知识产权概述 知识产权是…

RN_iOS项目部署流程实例

文章目录 1、环境配置1.1 安装node1.2 安装Watchman1.3 安装npm1.4 安装cocoapods 2、百家云demo下载3、运行百家云demo3.1 顺利的话3.2 踩过的坑(按这个目录流程走)3.2.1 npm install -g react-native-cli3.2.2 安装:npm install3.2.3 npm降…

新一代智能柔性换层跨巷道多车调度的HEGERLS托盘四向穿梭车物流解决方案

随着电子商务和智能制造技术的快速发展,对自动化仓储、密集仓储、自动搬运系统、自动识别、无线通信等多系统集成的需求也在不断增加,物流设备系统的密集化、自动化、智能化等技术也在不断完善。密集存储技术的优势是空间可用性高、运行模式高效、工作人…

Docker-Compose 入门到实战详尽笔记

本文首发自「慕课网」(www.imooc.com),想了解更多IT干货内容,程序员圈内热闻,欢迎关注"慕课网"或慕课网公众号! 作者:暮闲 | 慕课网讲师 使用过 Docker 的小伙伴们都知道&#xff0…

职场小白如何在工作中快速的升职加薪

缘起 近来连续两个季度很轻松的获得优秀,在这轻松的背后,一定有些原因支撑这领导给了这个评价。坦白说,最近两个季度,无一天加班,因为我们团队不提倡加班;我这边离领导较远,属于两个城市异地办…

一天吃透Java面试八股文

Java的特点 Java是一门面向对象的编程语言。面向对象和面向过程的区别参考下一个问题。 Java具有平台独立性和移植性。 Java有一句口号:Write once, run anywhere,一次编写、到处运行。这也是Java的魅力所在。而实现这种特性的正是Java虚拟机JVM。已编…

chatgpt赋能Python-pyhton如何安装

Python的安装方法 Python是一种高级编程语言,适用于多种开发需求,从网站构建到机器学习。其易用和灵活的语法使其成为一种非常受欢迎的编程语言。本文将向您介绍如何安装Python。 Python的安装步骤 以下是安装Python的步骤。 步骤1:下载P…

[笔记]初识Burpsuit

文章目录 前言一、安装配置1.1 环境1.2 安装过程1.3 科技过程 二、常用功能2.1 Manual penetration testing features2.2 Advanced/custom automated attacks2.3 Automated scanning for vulnerabilities2.4 Productivity tools2.5 Extensions 三、拓展功能 前言 Burp Suite(b…