给定一个已排序的链表的头 head
, 删除原始链表中所有重复数字的节点,只留下不同的数字 。返回 已排序的链表 。
示例 1:
输入:head = [1,2,3,3,4,4,5] 输出:,2,5]
示例 2:
输入:head = [1,1,1,2,3] 输出:[2,3]
提示:
- 链表中节点数目在范围
[0, 300]
内 -100 <= Node.val <= 100
- 题目数据保证链表已经按升序 排列
题解(三指针)
- 引入了虚拟头结点dummyHead,因为我们需要确定prev指向的结点必须不是要删除的结点,所以prev用来存储那些不重复的元素,fir指向prev的后继结点,sec来确定fir到sec-1要不要删除
- 初始化 prev=dummyHead fir=prev.next sec=fir.next
- 如果fir.val!=sec.val,那么就将prev fir sec都后移一位
- 如果fir.val==sec.val,那么就将sec一直移动,直到sec.val!=fir.val,然后删除fir到sec的结点,不包括sec
- 当sec==null,程序结束
JAVA代码实现
public ListNode deleteDuplicates(ListNode head) { ListNode dummyNode=new ListNode();//定义虚拟头节点 dummyNode.next=head;//将虚拟头节点与给的头节点链接起来 if (head==null||head.next==null){ return head; //如果只有一个结点,或者没有结点那么就直接返回 } ListNode prev=dummyNode; ListNode fir=prev.next; //因为在前面判断了head!=null 所以不会空指针异常 ListNode sec=fir.next;//因为在前面判断了head.next!=null 所以不会空指针异常 while (sec!=null){ if (fir.val!=sec.val){ prev=prev.next; fir=fir.next; sec=sec.next; }else { while(sec!=null && fir.val==sec.val){ sec=sec.next; } prev.next=sec; fir=prev.next; if (sec!=null) { sec = sec.next; } } } return dummyNode.next; }
递归实现
public ListNode deleteDuplicates(ListNode head) { //终止条件 if (head==null||head.next==null){ return head; } //判断头结点是不是要删除的结点 //如果不是,直接将头结点链接后面处理好的链表 if (head.val!=head.next.val){ head.next=deleteDuplicates(head.next); return head; }else { //如果是,则把这个结点全部都删完,找到下一个不为这个值的结点 ListNode nextHead= head.next; while (nextHead!=null&&head.val==nextHead.val){ nextHead=nextHead.next; } //为什么是return deleteDuplicates(nextHead); //因为找到这个头结点可能还是一个重复的结点,所以还需要去判断 return deleteDuplicates(nextHead); }