题目
编写代码,移除未排序链表中的重复节点。保留最开始出现的节点。
示例1:
输入:[1, 2, 3, 3, 2, 1]
输出:[1, 2, 3]
示例2:
输入:[1, 1, 1, 1, 2]
输出:[1, 2]
提示:
链表长度在[0, 20000]范围内。
链表元素在[0, 20000]范围内。
进阶:
如果不得使用临时缓冲区,该怎么解决?
解题思路
1.利用set进行去重
思路
- 遇到一个节点,先判断set中存不存在,不存在再存入set,存在则直接跳过。
- 【注意】需要删除节点的时候,p是不用前进的(也就是p不用等于p.next)
- 【注意】退出循环的条件这里只用判断p的下一个指针是否为空就行了,因为p已经是检测过不重复的指针了
代码
public class Test {
public static void main(String[] args) {
ListNode head = new ListNode(1);
head.next = new ListNode(2);
head.next.next = new ListNode(3);
head.next.next.next = new ListNode(3);
head.next.next.next.next = new ListNode(2);
head.next.next.next.next.next = new ListNode(1);
ListNode h = solution(head);//也就是输入了1-2-3-3-2-1 这条ListNode
while (h != null) {
System.out.println("h.val = " + h.val);
h = h.next;
}
}
public static ListNode solution(ListNode head) {
if (head == null) {
return null;
}
ListNode p = head;
HashSet<Integer> set = new HashSet<>();
set.add(head.val);
while (p.next != null) { // 这里只用判断p的下一个指针是否为空就行了,因为p已经是检测过不重复的指针了
if (set.contains(p.next.val)) {
p.next = p.next.next;
} else {
set.add(p.next.val);
p = p.next;
}
}
return head;
}
}
性能
2.不使用临时缓存,使用两重循环暴力求解
思路
- 也就是双指针…一个指针 i 指向一个节点,然后用指针 j 遍历其后面的节点
- j 如果遍历到节点与 i 的值重复(j.next.val = i.val),那么就修改链表结构删除该节点
- 【注意】因为涉及到了链表的节点删除,所以一定要用该指针的next指向要判断是否重复的节点,如果重复才能将其删除(p.next = p.next.next),之后切记p先别往前移动,因为删除一个next就相当于移动了一步。