算法第四十一天-排除排序链表中的重复元素Ⅱ

排除排序链表中的重复元素Ⅱ

题目要求

在这里插入图片描述

解题思路

题意:在一个有序链表中,如果一个节点的值出现不止一次,那么把这个节点删除掉
重点:有序链表,所以,一个节点的值出现不止一次,那么他们必相邻。

方法一:递归

链表和树的问题,一般都可以有递归和迭代两种写法。对于本题一定要记住是有序链表,值相同的节点会在一起。
1.1 递归函数定义
递归最基本的是要明白递归函数的定义!
递归函数直接使用题目给出的函数deleteDuplicates(head),它的含义是删除以head作为开头的有序链表,值出现重复的节点。
1.2 递归终止条件
终止条件就是能想到的基本的、不用继续递归处理的case

  • 如果head为空,那么肯定没有值出现反复的节点,直接返回head;
  • 如果head.next为空,那么说明链表中只有一个节点,也没有值出现重复的节点,也直接返回head

1.3 递归调用
什么时候需要调用递归呢?我们考虑两种情况:

  • 如果head.val != head.next.val,说明头节点的值不等于下一个节点的值,所以当前的head节点必须保留;但是head.next节点要不要保留呢?我们还不知道,需要head.next进行递归,即对head.next作为头节点的链表,去除值重复的节点。所以head.next = self.deleteDuplicates(head.next)
  • 如果head.val == head.next.val,说明头节点的值等于下一个节点的值,所以当前的head,节点必须删除;但是head.next节点要不要删除呢?我们还不知道,需要一直向后遍历寻找与head.val不等的节点。与haed.val相等的这一段链表都要删除,因此返回deleteDuplicates(move)

1.4 返回结果
题目让我们返回删除了值重复的节点后剩余的链表,结合上面两种递归调用的情况。

  • 如果head.val != head.next.val,头节点需要保留,因此返回的是head
  • 如果head.val == head.next.val,头节点需要删除,需要返回的是deleteDuplicates(move)

迭代

方法二:一次遍历

这里说的一次遍历,是说一次遍历、一遍统计相邻节点的值是否相等,如果值相等就继续后移找到值不等的位置,然后删除值相等的这个区间
其实这个思路很简单,跟递归方法中的while语句跳过所有值相等的节点的思路是一样的:如果curr.val == cur.next.val说明两个相邻节点值相等,所以继续猴戏,一直找到cur.val !=cure.next.val,此时的cur.next就是值不等的节点;
代码中用到了一个常见的技巧:dummy节点,也叫做哑节点
它在链表的迭代写法中非常常见,因为对于本题而言,我们可能会删除头节点head,为了维护一个不变的头节点,所以我们添加了dummy,让dummy.next = head,这样即使头节点被删除了,那么操作dummy.next指向新的链表头部,所以最终返回的也是dummy.next

方法三:利用计数,两次遍历

这个做法忽略了链表有序这个性质,使用了两次遍历,第一次遍历统计每个节点的值出现的次数,第二次遍历的时候,如果发现head.next的val出现次数不是1次,则需要删除head.next

代码

递归:

class Solution:
    def deleteDuplicates(self, head: ListNode) -> ListNode:
        if not head or not head.next:
            return head
        if head.val != head.next.val:
            head.next = self.deleteDuplicates(head.next)
        else:
            move = head.next
            while move and head.val == move.val:
                move = move.next
            return self.deleteDuplicates(move)
        return head

迭代:
一次遍历:

class Solution:
    def deleteDuplicates(self, head: ListNode) -> ListNode:
        if not head or not head.next:
            return head
        dummy = ListNode(0)
        dummy.next = head
        pre = dummy
        cur = head
        while cur:
            while cur.next and cur.val ==cur.next.val:
                cur = cur.next
            if pre.next ==cur:
                pre = pre.next
            else:
                pre.next = cur.next
            cur =cur.next
        return dummy.next

两次遍历:

class Solution:
    def deleteDuplicates(self, head):
        dummy = ListNode(0)
        dummy.next = head
        val_list = []
        while head:
            val_list.append(head.val)
            head = head.next
        counter = collections.Counter(val_list)
        head = dummy
        while head and head.next:
            if counter[head.next.val] != 1:
                head.next = head.next.next
            else:
                head = head.next
        return dummy.next

复杂度分析

递归:
时间复杂度: O ( N ) O(N) O(N)
空间复杂度: O ( N ) O(N) O(N)

迭代:
一次遍历
时间复杂度: O ( N ) O(N) O(N)
空间复杂度: O ( 1 ) O(1) O(1)

两次遍历
时间复杂度: O ( N ) O(N) O(N)
空间复杂度: O ( N ) O(N) O(N)

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

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

相关文章

CMC学习系列 (7):β 范围 EEG-EMG 相干性与皮质光谱功率有关

CMC学习系列:β 范围 EEG-EMG 相干性与皮质光谱功率有关 0. 引言1. 主要贡献2. 方法2.1 目标2.2 实验范式2.3 数据处理和分析 3. 结果4. 讨论5. 总结欢迎来稿 论文地址:https://www.sciencedirect.com/science/article/abs/pii/S1053811907001760 论文题目&#xff…

一、接口自动化之pytest 运行参数

1、在跟目录下创建一个配置项pytest.ini [pytest] testpaths./testcases markersp0:高于优先级test:测试环境pro:生成环境2、打标签 3、运行命名pytest -m "p0"

单链表详解(无哨兵位),实现增删改查

1.顺序表对比单链表的缺点 中间或头部插入时,需要移动数据再插入,如果数据庞大会导致效率降低每次增容就需要申请空间,而且需要拷贝数据,释放旧空间增容造成浪费,因为一般都是以2倍增容 2.链表的基础知识 链表也是线…

蓝桥杯 — — 数数

数数 友情链接:数数 题目: 思路: 这道题目主要用到了埃氏筛法(Sieve of Eratosthenes)来快速求解质数的方法,思路很巧妙,并且用到了动态规划的思想。 我们首先定义两个数组mk和p&#xff0c…

LPA3399Pro搭建Qt开发环境

将以前的开发文档在此做一个记录。 一、介绍 Qt是一个跨平台的应用程序开发框架,支持多种操作系统和硬件架构,包括ARM架构的Linux。 RK3399Pro是一款基于ARM架构的处理器,用于嵌入式系统。可以在RK3399上搭建Qt开发环境,进行项目…

C语言学习笔记之结构体(一)

目录 什么是结构体? 结构体的声明 结构体变量的定义和初始化 结构体成员的访问 结构体传参 什么是结构体? 在现实生活中的很多事物无法用单一类型的变量就能描述清楚,如:描述一个学生,需要姓名,年龄&a…

演示:单包攻击,扫描类攻击,畸形报文攻击[Land攻击,泪滴攻击,ip地址欺骗]。配置防火墙进行防御

浏览上篇博客进行环境搭建 单包攻击 单包攻击(Single Packet Attack)是一种利用网络协议或应用程序中的漏洞进行的攻击方式。这种攻击通常只需要发送一个精心构造的数据包,就能够触发目标系统的漏洞,导致攻击者能够执行非授权的…

JVM修炼之路【12】- GC调优 、性能调优

上一篇中 我们详细讲了内存溢出 内存泄漏 还有相关的案例。 这篇博客中我们主要了解一下GC调优。 有些新手可能会有一点 疑问—— 这两者不是一回事吗?? 其实说一回事 也没错 因为GC调优本质上还是针对 堆上的内存 只不过前面我们关注的侧重点在于 不合…

关于机器学习中贝叶斯学习(Bayesian Learning)计算公式的理解

一、引言 在《统计学习的分类概述》中介绍了贝叶斯学习的概念和计算公式,可以看到这个公式就是概率统计理论中的贝叶斯公式,但在机器学习中这个公式与概率统计中的理解要复杂得多。 二、贝叶斯学习公式及各组成因子的含义 要理解贝叶斯学习公式&#…

【Spring Security】1.Spring Security介绍 功能介绍

文章目录 一、Spring Security介绍二、功能介绍 一、Spring Security介绍 官方文档:https://docs.spring.io/spring-security/reference/index.html 官网解释:Spring Security 是一个提供 身份验证、授权 和 针对常见攻击的保护 的框架。 它为 保护命令…

运放噪声评估的来龙去脉

运放噪声评估的来龙去脉 友情提示,运放电路的噪声分析还是比较复杂的,不论是基础理论还是对应的推导过程,都不是特别容易。考虑到兄弟们的基础参差不齐,所以我还是尽量说清楚点,这样导致看起来就有点罗里吧嗦&#xff…

刷题之动态规划-回文串

前言 大家好,我是jiantaoyab,开始刷动态规划的回文串类型相关的题目 动态规划5个步骤 状态表示 :dp数组中每一个下标对应值的含义是什么>dp[i]表示什么状态转移方程: dp[i] 等于什么1 和 2 是动态规划的核心步骤,…

市场复盘总结 20240412

仅用于记录当天的市场情况,用于统计交易策略的适用情况,以便程序回测 短线核心:不参与任何级别的调整,采用龙空龙模式 一支股票 10%的时候可以操作, 90%的时间适合空仓等待 二进三: 进级率 50% 最常用的二…

iOS开发之为什么需要引用计数

iOS开发之为什么需要引用计数 在iOS开发中,Objective-C与Swift语言都是通过引用计数进行内存管理,实际上Python、Ruby、C等语言也提供了基于引用计数的内存管理方式,它们有一个共同点,那就是都是面向对象的编程语言。 引用计数可…

响应式布局(其次)

响应式布局 一.响应式开发二.bootstrap前端开发框架1.原理2.优点3.版本问题4.使用(1)创建文件夹结构(2)创建html骨架结构(3)引入相关样式(4)书写内容 5.布局容器(已经划分…

Cascader 级联选择器 - 选择器最后一级数据为空

原因:将扁平数据转化为树形数据时,给每个项都添加了 children export const transList2Tree (list, rootPid) > {const result []list.forEach(item > {if (item.pid rootPid) {const children transList2Tree(list, item.id)item.children …

c语言多功能计算软件170

定制魏:QTWZPW,获取更多源码等 目录 题目 要求 主要代码片段 题目 设计一个计算器软件,具备如下功能提示界面。 要求 设计出界面,注意界面名称最后为自己的姓名;(20分)能够实现加、减、乘、…

【Godot4.2】CanvasItem绘图函数全解析 - 3.绘制纹理

概述 前两节我们讲述了常见几何图形绘制以及对几何图形应用变换的基础知识。 本节我们来讲如何在CanvasItem中绘制纹理。 系列目录 0.概述1.绘制简单图形2.设定绘图变换3.绘制纹理4.绘制样式盒5.绘制字符和字符串6.TextLine和TextParagraph详解7.自定义节点TextBoard8.绘制点…

C语言 函数——函数封装与程序的健壮性

目录 函数封装(Encapsulation) 如何增强程序的健壮性? 如何保证不会传入负数实参? 函数设计的基本原则 函数封装(Encapsulation) 外界对函数的影响——仅限于入口参数 函数对外界的影响——仅限于一个…

MySQL前缀索引(3/16)

前缀索引 前缀索引:MySQL支持前缀索引,允许定义字符串的一部分作为索引。如果不指定前缀长度,索引将包含整个字符串。前缀索引可以节省空间,但可能会增加查询时的记录扫描次数(因为会查询到多个前缀相同的数据&#x…