【问题描述】[简单]

编写代码,移除未排序链表中的重复节点。保留最开始出现的节点。示例1:输入:[1, 2, 3, 3, 2, 1]输出:[1, 2, 3]
示例2:输入:[1, 1, 1, 1, 2]输出:[1, 2]
提示:链表长度在[0, 20000]范围内。
链表元素在[0, 20000]范围内。
进阶:如果不得使用临时缓冲区,该怎么解决?

【解答思路】

1. Set/哈希集合

对给定的链表进行一次遍历,并用一个哈希集合(HashSet)来存储所有出现过的节点val

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

class Solution {public ListNode removeDuplicateNodes(ListNode head) {if (head == null) {return head;}Set<Integer> occurred = new HashSet<Integer>();occurred.add(head.val);ListNode pos = head;// 枚举前驱节点while (pos.next != null) {// 当前待删除节点ListNode cur = pos.next;if (occurred.add(cur.val)) {pos = pos.next;} else {pos.next = pos.next.next;}}pos.next = null;return head;}
}

另一种写法

  public ListNode removeDuplicateNodes(ListNode head) {if(head == null){return null;}Set<Integer> set = new HashSet<>();ListNode pre =head;ListNode cur = head.next;set.add(head.val);while(cur!=null){if(set.contains(cur.val) ){pre.next = cur.next;// 连接到最后的nullcur= cur.next;}else{set.add(cur.val);pre = cur;cur =cur.next;}}return head;}
2. 两重循环(冒泡排序) 进阶解法

在给定的链表上使用两重循环,其中第一重循环从链表的头节点开始,枚举一个保留的节点,这是因为我们保留的是「最开始出现的节点」。第二重循环从枚举的保留节点开始,到链表的末尾结束,将所有与保留节点相同的节点全部移除。
第一重循环枚举保留的节点本身,而为了编码方便,第二重循环可以枚举待移除节点的前驱节点,方便我们对节点进行移除。这样一来,我们使用「时间换空间」的方法,就可以不使用临时缓冲区解决本题了。

时间换空间

时间复杂度:O(N^2) 空间复杂度:O(1)

class Solution {public ListNode removeDuplicateNodes(ListNode head) {ListNode ob = head;while (ob != null) {ListNode oc = ob;while (oc.next != null) {if (oc.next.val == ob.val) {oc.next = oc.next.next;} else {oc = oc.next;}}ob = ob.next;}return head;}
}

【总结】

1.枚举前驱节点 删除节点方便

2.时间空间相互tradeoff
3.链表题目画图 切忌心烦意乱

转载链接:https://leetcode-cn.com/problems/remove-duplicate-node-lcci/solution/yi-chu-zhong-fu-jie-dian-by-leetcode-solution/

[程序员面试金典][JAVA][第02.01题][移除重复节点][Set][双指针]相关推荐

  1. 程序员面试金典 - 面试题 02.01. 移除重复节点(哈希set)

    1. 题目 编写代码,移除未排序链表中的重复节点.保留最开始出现的节点. 示例1:输入:[1, 2, 3, 3, 2, 1]输出:[1, 2, 3]示例2:输入:[1, 1, 1, 1, 2]输出:[ ...

  2. 程序员面试金典适合java么,【程序员面试金典】面试题 01.03. URL化(示例代码)

    题目 URL化.编写一种方法,将字符串中的空格全部替换为%20.假定该字符串尾部有足够的空间存放新增字符,并且知道字符串的"真实"长度.(注:用Java实现的话,请使用字符数组实现 ...

  3. 程序员面试金典 - 面试题 02.04. 分割链表

    1. 题目 编写程序以 x 为基准分割链表,使得所有小于 x 的节点排在大于或等于 x 的节点之前.如果链表中包含 x,x 只需出现在小于 x 的元素之后(如下所示).分割元素 x 只需处于" ...

  4. 程序员面试金典 - 面试题 05.01. 插入(位运算)

    1. 题目 插入.给定两个32位的整数 N 与 M,以及表示比特位置的 i 与 j. 编写一种方法,将 M 插入 N,使得 M 从 N 的第 j 位开始,到第 i 位结束. 假定从 j 位到 i 位足 ...

  5. 程序员面试金典 - 面试题 04.01. 节点间通路(图的遍历)

    1. 题目 节点间通路.给定有向图,设计一个算法,找出两个节点之间是否存在一条路径. 示例1:输入:n = 3, graph = [[0, 1], [0, 2], [1, 2], [1, 2]],st ...

  6. 程序员面试金典 - 面试题 03.01. 三合一(数组栈)

    1. 题目 三合一.描述如何只用一个数组来实现三个栈. 你应该实现push(stackNum, value).pop(stackNum).isEmpty(stackNum).peek(stackNum ...

  7. 程序员面试金典 - 面试题 16.01. 交换数字(位运算swap)

    1. 题目 编写一个函数,不用临时变量,直接交换numbers = [a, b]中a与b的值. 示例: 输入: numbers = [1,2] 输出: [2,1]提示: numbers.length ...

  8. 程序员面试金典 - 面试题 02.05. 链表求和

    1. 题目 给定两个用链表表示的整数,每个节点包含一个数位. 这些数位是反向存放的,也就是个位排在链表首部. 编写函数对这两个整数求和,并用链表形式返回结果. 示例: 输入:(7 -> 1 -& ...

  9. 程序员面试金典 - 面试题 10.01. 合并排序的数组

    1. 题目 给定两个排序后的数组 A 和 B,其中 A 的末端有足够的缓冲空间容纳 B. 编写一个方法,将 B 合并入 A 并排序. 初始化 A 和 B 的元素数量分别为 m 和 n. 示例: 输入: ...

最新文章

  1. 硬件安全模块如何启用AUTOSAR
  2. 二维几何变换---OpenGL几何变换编程示例
  3. 用D触发器构造RAM存储器
  4. android textwatcher 延时,Java-防止两次在android的textwatcher中运行
  5. 征战蓝桥 —— 2017年第八届 —— C/C++A组第9题——分巧克力
  6. Spring Boot2 集成 jasypt 3.0.4 配置文件敏感信息加密
  7. Spring IO platform
  8. Luogu P4774 / LOJ2721 【[NOI2018]屠龙勇士】
  9. 【linux学习笔记五】帮助命令
  10. C# Asp.net 制作一个windows服务
  11. html++hint标签,html5新标签总结
  12. 自制的基Ogre的场景编辑器—OgreSE
  13. 2022,云上开发的新纪元
  14. mysql随机抽样方法_MySQL中随机抽样
  15. c51单片机之数码管显示(共阳极数码管)
  16. PHP正则过滤处理微信昵称中emoji字符的方法(导出excel)
  17. 尚硅谷nginx笔记
  18. leetcode 最长单词
  19. 3d max材质添加透明贴图异常
  20. I/Q信号解调分析过程

热门文章

  1. HBase 手动 flush 机制梳理
  2. Web中的鼠标自动移动
  3. 1.怎样定制VC#DataGrid列标题?
  4. springmvc限流解决方案
  5. 2018java基础面试题(我自己用的,面试好多家公司基本会问到的问题和技术)
  6. eslint 设置全局 变量
  7. 计算机win10启动慢,Win10 开机慢/Win10启动慢的常见原因
  8. IO流的体系及FileReader、FileWriter
  9. sqlserver note
  10. html文本框样式大全,HTML文本框样式大全