当前位置: 首页 > 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)已排序链表,最优选择

总结

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

http://www.xdnf.cn/news/310663.html

相关文章:

  • 电子电器架构 --- 网关转发时延解析
  • PostgreSQL存储过程“多态“实现:同一方法名支持不同参数
  • 亚马逊Q1财报公布!营收增长9%至1557亿美元
  • QT Sqlite数据库-教程03 插入数据-下
  • 信息论05:信息论中的条件熵——从不确定性量化到机器学习实战
  • opencv实战:银行卡卡号识别
  • 效率提升利器:解锁图片处理新姿势
  • MySQL的内置函数与复杂查询
  • 【Python面向对象编程】类与对象的深度探索指南
  • Python训练打卡Day17
  • 让混乱的讨论变成有效产出的智能助手
  • 51单片机入门教程——AT24C02(I2C 总线)
  • QGIS分割平行四边形
  • ctfshow web入门 web52
  • 汽车行业EDI教程【北美X12标准】——X12转换配置
  • Fluent UDF底层实现逻辑解析及示例
  • 养生融入生活,畅享健康人生
  • 7.9/Q1,Charls最新文章解读
  • PySide6使用资源文件
  • 6GHz频段受限:WiFi 7部署的“最后一公里”难题如何破局
  • 白平衡色温坐标系下自适应计算白点权重的方法
  • app根据蓝牙名字不同,匹配不同的产品型号,显示对应的UI界面
  • 探索SQLMesh中的Jinja宏:提升SQL查询的灵活性与复用性
  • [学习]RTKLib详解:pntpos.c与postpos.c
  • JVM堆的分代机制
  • Linux 内核空间与用户空间:概念、差异与协作机制
  • 端口隔离基本配置
  • Weston显示系统中单屏幕独立旋转配置指南
  • Javase 基础加强 —— 06 Stream流
  • 企业CMS中的内容中台是什么?