https://oj.leetcode.com/problems/remove-duplicates-from-sorted-list-ii/
Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numbers from the original list.
For example,
Given 1->2->3->3->4->4->5
, return 1->2->5
.
Given 1->1->1->2->3
, return 2->3
.
解题思路:
这道题与前面的Remove Duplicates from Sorted List相似,却采用了不同的思路。Remove Duplicates from Sorted List 是当前节点与前面的值比较,如果比前面的大,就加入。而本题是,当前节点与后面节点相比,如果后面节点比当前节点大,而且当前节点比再前一个值小,就加入。代码如下。
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { * val = x; * next = null; * } * } */ public class Solution { public ListNode deleteDuplicates(ListNode head) { if(head == null){ return null; } ListNode dummyNode = new ListNode(head.val - 1); dummyNode.next = head; ListNode preNode = dummyNode; ListNode currentNode = head; ListNode nextNode = head.next; ListNode keepNode = preNode; while(nextNode != null){ if(preNode.val < currentNode.val && currentNode.val < nextNode.val){ keepNode.next = currentNode; keepNode = keepNode.next; } preNode = preNode.next; currentNode = currentNode.next; nextNode = nextNode.next; } //循环结束,这时preNode为倒数第二个节点,currentNode为最后一个节点 if(preNode.val < currentNode.val){ keepNode.next = currentNode; keepNode = keepNode.next; } keepNode.next = null; return dummyNode.next; } }
这道题的关键在于要时刻保留三个指针,只有中间那个的值大于前面的并且小于后面的,才能加入中间那个节点。还需要注意最后一轮,preNode为倒数第二个节点,currentNode为最后一个节点的时候,要再加一次判断。最后,一定要注意,把keepNode.next置为null,否则遇到1-1这样的要出错。
下面的代码是另一种实现,思路略微不同,但是代码要复杂很多。当前节点与后面节点相比,如果后面节点比当前节点大,就要把当前节点加入。如果相等的话,把当前值作为重复值(invalidValue),这样在判断1-3-3-4-4这样情况的的第二个3时,虽然后面的4大于当前的3,但是3==invalidValue,所以3不能加入。
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { * val = x; * next = null; * } * } */ public class Solution { public ListNode deleteDuplicates(ListNode head) { if(head == null){ return null; } ListNode dummyNode = new ListNode(head.val - 1); dummyNode.next = head; ListNode keepNode = dummyNode; ListNode traverseNode = dummyNode.next; int invalidVal = dummyNode.val; while(traverseNode != null){ //如果traverseNode的后一个节点为空 if(traverseNode.next == null){ //看看traverseNode本身是不是重复的节点,不是就加入 if(traverseNode.val != invalidVal){ keepNode.next = traverseNode; keepNode = keepNode.next; traverseNode = traverseNode.next; }else{ traverseNode = traverseNode.next; } }else{ //traverseNode的后一个节点大于它,就把它加入,还要注意1-3-3-4-4,traverseNode在第二个3的情况 //所以要加入一个invalidVal记录当前的重复值,不能加入 if(traverseNode.next.val > traverseNode.val && traverseNode.val != invalidVal){ keepNode.next = traverseNode; keepNode = keepNode.next; traverseNode = traverseNode.next; }else{//如果traverseNode的后一个节点等于它 invalidVal = traverseNode.val; traverseNode = traverseNode.next; } } } keepNode.next = null; return dummyNode.next; } }
update 2015/05/19:
二刷
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ public class Solution { public ListNode deleteDuplicates(ListNode head) { if(head == null || head.next == null) { return head; } ListNode dummy = new ListNode(0); int pre = head.val - 1; ListNode cur = head; ListNode slow = dummy; while(cur != null) { if(cur.val != pre && (cur.next == null || cur.val != cur.next.val)) { slow.next = cur; slow = slow.next; } else { slow.next = null; } pre = cur.val; cur = cur.next; } return dummy.next; } }
// 20180806
/** * Definition for singly-linked list. * public class ListNode { * int val; * ListNode next; * ListNode(int x) { val = x; } * } */ class Solution { public ListNode deleteDuplicates(ListNode head) { if (head == null || head.next == null) { return head; } ListNode dummy = new ListNode(head.val - 1); dummy.next = head; ListNode pre = dummy; ListNode next = dummy.next; while (next != null && next.next != null) { if (next.val == next.next.val) { while (next.next != null && next.val == next.next.val) { next = next.next; } pre.next = next.next; next = next.next; } else { pre = pre.next; next = next.next; } } return dummy.next; } }