题目
给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现的数字。
示例 1:
输入: 1->2->3->3->4->4->5
输出: 1->2->5
解析
链表中的常见技巧,建立哑结点,本题也是。
- 在原链表前加一个哑结点,将cur指向这个哑结点。
- 判断cur.next.val是否等于cur.next.next.val
- 如果等于(即有重复),创建一个临时节点temp = cur.next,循环判断temp.val是否等于temp.next.val。如果等于temp 向后移,直到没有重复位置。此时的temp保存着重复元素的最后一个,我们也需要将这个唯一的元素也删除。执行cur.next = temp.next。
- 如果不等于,直接cur后移一位:cur = cure.next。
建头结点为哑结点的好处,避免了从头结点开始就有重复元素,要删除头结点的极端情况。代码如下:
这是别人的代码:
public static ListNode deleteDuplicates(ListNode head) {
ListNode newhead = new ListNode(0);// 构建哑结点
newhead.next = head; // 给原链表加一个哑结点
ListNode cur = newhead; // 将cur赋给哑结点
// 使用哑结点巧妙的避开了删除头结点的极端情况
while(cur.next != null && cur.next.next !=null) {
if(cur.next.val == cur.next.next.val) {
ListNode temp = cur.next;
while(temp!=null &&temp.next!=null&&temp.val== temp.next.val )
{ temp = temp.next;}
cur.next = temp.next;
} else {
cur = cur.next;
}
}
return newhead.next;
}
我自己的思路,虽然也建立了哑结点,但是使用了辅助指针pre、cur和一个标志位。想法没有别人的简洁,但是两份代码用时都是1ms.
public static ListNode deleteDuplicates2(ListNode head) {
ListNode newHead = new ListNode(0); // 构建哑结点
newHead.next = head;
ListNode pre = newHead;
ListNode cur = head;
Boolean flag = false; // 建立哑结点
while(cur!=null && cur.next!=null) {
if(cur.val == cur.next.val) {
cur.next = cur.next.next;
flag = true;// 有重复的将flag设置为true,方便后面删除当前的cur
}else {
if(flag) {
// 如果前面有重复的,则要删除当前的cur
pre.next = cur.next;
cur = cur.next;
// 删除当前的cur之后要将flag设置为false
flag = false;
}else {
// 如果没有重复的,pre与cur都向后移位
pre = cur;
cur = cur.next;
}
}
}
// 防止尾重复 再判断一次
if(flag) {
pre.next = cur.next;
cur = cur.next;
}
return newHead.next;