面试题 02.01. 移除重复节点
题目链接
思路分析
原题
这个题其实很简单,我们拿一个缓冲区去记录出现过的数字就可以了。如果缓冲区中有当前结点的值的话,我们直接跳到下一个,否则我们就把当前结点纳入到缓冲区中,并且使上一个结点的next指针指向当前结点,当然还要把当前结点的next指针指向空。
这个思路中的缓冲区可以用set,也可以用数组,因为题目说明链表元素在[0, 20000]范围内。
进阶题
不使用缓冲区,我们只能用时间换空间的思想,每次都把链表中与当前元素重复的结点删除掉,然后再把当前结点纳入到结果集中。
实现代码
原题代码
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode removeDuplicateNodes(ListNode head) {
HashSet<Integer> set = new HashSet<>();
ListNode node = head;
ListNode dummy = new ListNode(-1);
ListNode next = dummy;
while(node != null){
if(!set.contains(node.val)){
set.add(node.val);
next.next = node;
next = next.next;
node = node.next;
next.next = null;
continue;
}
node = node.next;
}
return dummy.next;
}
}
进阶问题代码
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode removeDuplicateNodes(ListNode head) {
if(head==null) return null;
ListNode dummy=new ListNode(0);
dummy.next=head;
ListNode pre=dummy;
while(pre.next!=null){
ListNode cur=pre.next;
while(cur.next!=null){
if(pre.next.val==cur.next.val){
cur.next=cur.next.next;
}else{
cur=cur.next;
}
}
pre=pre.next;
}
return dummy.next;
}
}
总结
这个题的进阶问题我第一次想直接拿归并排序去做,在合并的时候去除掉相同的元素,后来发现第五个测试用例就WA了,才明白这个题的主要目的是让我们不要修改链表中各个元素之间的顺序。这个真的是尴尬~~
在这里贴个链表去重的归并排序算法的代码吧。
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode removeDuplicateNodes(ListNode head) {
return mergeSort(head);
}
private ListNode mergeSort(ListNode head){
if(head == null || head.next == null){
return head;
}
ListNode headRight = findMiddle(head);
ListNode left = mergeSort(head);
ListNode right = mergeSort(headRight);
return merge(left,right);
}
private ListNode findMiddle(ListNode head){
ListNode fast = head;
ListNode slow = head;
while(fast.next != null && fast.next.next != null){
fast = fast.next.next;
slow = slow.next;
}
ListNode temp = slow.next;
slow.next = null;
return temp;
}
private ListNode merge(ListNode l, ListNode r){
ListNode dummy = new ListNode(-1);
ListNode node = dummy;
while(l != null && r != null){
if(l.val < r.val){
node.next = l;
l = l.next;
}else{
node.next = r;
if(l.val == r.val){
l = l.next;
}
r = r.next;
}
node = node.next;
}
while(l != null){
node.next = l;
node = node.next;
while(l != null && l.val == node.val){
l = l.next;
}
}
while(r != null){
node.next = r;
node = node.next;
while(r != null && r.val == node.val){
r = r.next;
}
}
return dummy.next;
}
}