当前位置: 首页 > news >正文

删除排序链表中的重复元素:三种解法详解

问题描述

给定一个已排序的链表的头节点 head,要求删除所有重复元素,使得每个元素只出现一次。返回处理后的已排序链表。下面是leetcode题目如果感兴趣可以尝试一下。

方法一:递归解法

思路

递归法通过维护一个 ArrayList 来记录已遍历过的节点值。具体步骤如下:

  1. 将当前节点的值加入列表。

  2. 递归处理下一个节点:

    • 如果下一个节点的值已存在于列表中,则跳过该节点(修改前驱节点的指针)。

    • 否则,继续递归处理。

class Solution {public ListNode deleteDuplicates(ListNode head) {if (head == null) return head;ArrayList<Integer> numbers = new ArrayList<>();numbers.add(head.val);deletenode(head, head.next, numbers);return head;}private void deletenode(ListNode pre, ListNode node, ArrayList<Integer> numbers) {if (node == null) return;if (numbers.contains(node.val)) {pre.next = node.next; // 删除当前节点deletenode(pre, node.next, numbers); // 继续处理下一个节点} else {numbers.add(node.val);deletenode(node, node.next, numbers); // 更新前驱节点}}
}

复杂度分析

  • 时间复杂度:O(n²),因为 ArrayList.contains() 的时间复杂度为 O(n)。

  • 空间复杂度:O(n),递归调用栈和列表的空间。

缺点

  • 递归深度可能达到链表长度,导致栈溢出。

  • 重复值检查效率低。

方法二:迭代解法

思路

通过迭代遍历链表,使用 ArrayList 记录已存在的值。遇到重复值时,直接修改前驱节点的指针。

class Solution {public ListNode deleteDuplicates(ListNode head) {if (head == null) return head;ArrayList<Integer> numbers = new ArrayList<>();numbers.add(head.val);ListNode pre = head;ListNode node = head.next;while (node != null) {if (numbers.contains(node.val)) {pre.next = node.next; // 跳过重复节点} else {numbers.add(node.val);pre = node; // 更新前驱节点}node = node.next; // 移动指针}return head;}
}

复杂度分析

  • 时间复杂度:O(n²),ArrayList.contains() 的线性检查导致性能瓶颈。

  • 空间复杂度:O(n),存储已遍历值的列表。

缺点

  • 空间复杂度较高,不适用于大规模数据。

方法三:直接遍历(最优解)

思路

利用链表已排序的特性,只需比较相邻节点的值:

优点

  • 若当前节点与下一节点的值相同,则跳过下一节点。

  • 否则,移动指针继续遍历。

    class Solution {public ListNode deleteDuplicates(ListNode head) {if (head == null) return head;ListNode cur = head;while (cur.next != null) {if (cur.val == cur.next.val) {cur.next = cur.next.next; // 删除重复节点} else {cur = cur.next; // 移动指针}}return head;}
    }

    复杂度分析

  • 时间复杂度:O(n),只需一次遍历。

  • 空间复杂度:O(1),无需额外空间。

  • 高效且节省内存,完美利用链表有序的特性。

方法对比

方法时间复杂度空间复杂度适用场景
递归解法O(n²)O(n)小规模数据,不推荐实际使用
迭代+ArrayListO(n²)O(n)未排序链表,但性能较差
直接遍历O(n)O(1)已排序链表,最优选择

总结

对于已排序链表,方法三是最优解,其时间复杂度和空间复杂度均为最优。递归法和迭代法虽然逻辑简单,但在处理大规模数据时性能不足。建议根据链表是否有序选择合适的算法。

相关文章:

  • 【Python-Day 10】Python 循环控制流:while 循环详解与 for 循环对比
  • ETL交通行业案例丨某大型铁路运输集团ETL数据集成实践
  • 购物数据分析
  • 双系统电脑中如何把ubuntu装进外接移动固态硬盘
  • 云境天合水陆安全漏电监测仪—迅速确定是否存在漏电现象
  • 算法每日一题 | 入门-顺序结构-三角形面积
  • 第十一届蓝桥杯 2020 C/C++组 蛇形填数
  • 第15章 Python数据类型详解之分解理解:基础数据类型常见易错点和性能优化篇
  • 【WPS】怎么解决“word的复制表格”粘贴到“excel的单元格”变多行单元格的问题
  • 浅谈 - GPTQ为啥按列量化
  • JavaSE基础概述--Lambda表达式,方法引用,基础算法,异常以及序列化
  • pywinauto通过图片定位怎么更加精准的识别图片?
  • 关于tftpboot的用法
  • 计算机中的逻辑运算
  • 关于串口读写NAND闪存的用法
  • 多线程系列五:面试中常考的单例模式
  • SQL 与 Python:日期维度表创建的不同选择
  • LINUX——例行性工作
  • LeetCode 220 存在重复元素 III 题解
  • 高铁座位指示灯系统技术深度解析:从物联网到智慧出行的实践路径
  • 诺和诺德一季度减重版司美格鲁肽收入增83%,美国市场竞争激烈下调全年业绩预期
  • 央行、证监会:科技创新债券含公司债券、企业债券、非金融企业债务融资工具等
  • 赵乐际:深入学习贯彻习近平生态文明思想,推动森林法全面有效贯彻实施
  • 特朗普称不会为了和中国谈判而取消对华关税,外交部回应
  • 一季度全国30强城市出炉:谁能更进一步?谁掉队了?
  • 市场监管总局发布《城镇房屋租赁合同(示范文本)》