[程序员面试金典][JAVA][第02.01题][移除重复节点][Set][双指针]
【问题描述】[简单]
编写代码,移除未排序链表中的重复节点。保留最开始出现的节点。示例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][双指针]相关推荐
- 程序员面试金典 - 面试题 02.01. 移除重复节点(哈希set)
1. 题目 编写代码,移除未排序链表中的重复节点.保留最开始出现的节点. 示例1:输入:[1, 2, 3, 3, 2, 1]输出:[1, 2, 3]示例2:输入:[1, 1, 1, 1, 2]输出:[ ...
- 程序员面试金典适合java么,【程序员面试金典】面试题 01.03. URL化(示例代码)
题目 URL化.编写一种方法,将字符串中的空格全部替换为%20.假定该字符串尾部有足够的空间存放新增字符,并且知道字符串的"真实"长度.(注:用Java实现的话,请使用字符数组实现 ...
- 程序员面试金典 - 面试题 02.04. 分割链表
1. 题目 编写程序以 x 为基准分割链表,使得所有小于 x 的节点排在大于或等于 x 的节点之前.如果链表中包含 x,x 只需出现在小于 x 的元素之后(如下所示).分割元素 x 只需处于" ...
- 程序员面试金典 - 面试题 05.01. 插入(位运算)
1. 题目 插入.给定两个32位的整数 N 与 M,以及表示比特位置的 i 与 j. 编写一种方法,将 M 插入 N,使得 M 从 N 的第 j 位开始,到第 i 位结束. 假定从 j 位到 i 位足 ...
- 程序员面试金典 - 面试题 04.01. 节点间通路(图的遍历)
1. 题目 节点间通路.给定有向图,设计一个算法,找出两个节点之间是否存在一条路径. 示例1:输入:n = 3, graph = [[0, 1], [0, 2], [1, 2], [1, 2]],st ...
- 程序员面试金典 - 面试题 03.01. 三合一(数组栈)
1. 题目 三合一.描述如何只用一个数组来实现三个栈. 你应该实现push(stackNum, value).pop(stackNum).isEmpty(stackNum).peek(stackNum ...
- 程序员面试金典 - 面试题 16.01. 交换数字(位运算swap)
1. 题目 编写一个函数,不用临时变量,直接交换numbers = [a, b]中a与b的值. 示例: 输入: numbers = [1,2] 输出: [2,1]提示: numbers.length ...
- 程序员面试金典 - 面试题 02.05. 链表求和
1. 题目 给定两个用链表表示的整数,每个节点包含一个数位. 这些数位是反向存放的,也就是个位排在链表首部. 编写函数对这两个整数求和,并用链表形式返回结果. 示例: 输入:(7 -> 1 -& ...
- 程序员面试金典 - 面试题 10.01. 合并排序的数组
1. 题目 给定两个排序后的数组 A 和 B,其中 A 的末端有足够的缓冲空间容纳 B. 编写一个方法,将 B 合并入 A 并排序. 初始化 A 和 B 的元素数量分别为 m 和 n. 示例: 输入: ...
最新文章
- 硬件安全模块如何启用AUTOSAR
- 二维几何变换---OpenGL几何变换编程示例
- 用D触发器构造RAM存储器
- android textwatcher 延时,Java-防止两次在android的textwatcher中运行
- 征战蓝桥 —— 2017年第八届 —— C/C++A组第9题——分巧克力
- Spring Boot2 集成 jasypt 3.0.4 配置文件敏感信息加密
- Spring IO platform
- Luogu P4774 / LOJ2721 【[NOI2018]屠龙勇士】
- 【linux学习笔记五】帮助命令
- C# Asp.net 制作一个windows服务
- html++hint标签,html5新标签总结
- 自制的基Ogre的场景编辑器—OgreSE
- 2022,云上开发的新纪元
- mysql随机抽样方法_MySQL中随机抽样
- c51单片机之数码管显示(共阳极数码管)
- PHP正则过滤处理微信昵称中emoji字符的方法(导出excel)
- 尚硅谷nginx笔记
- leetcode 最长单词
- 3d max材质添加透明贴图异常
- I/Q信号解调分析过程