1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| class Solution { public ListNode deleteDuplicates(ListNode head) { if (head == null || head.next == null) { return head; } ListNode dummy = new ListNode(0); ListNode curr = head, ptr = head, prev = dummy; dummy.next = head; while (curr != null) { int count = 0; while (ptr != null && ptr.val == curr.val) { ptr = ptr.next; count += 1; } if (count > 1) { prev.next = ptr; } else { prev = curr; } curr = ptr; } return dummy.next; } }
|
需要维护一个prev这个pointer以及new一个dummy并指向head, 防止可能出现要移除开头的重复nodes. 如果是间内的话, 用prev就ok了. 因为这里我们要移除所有的重复的, 而不是只保留一个. 因此需要prev这个pointer.
这个加dummy head的方法叫做: Sentinel Head.
时间复杂度: O(n)
空间复杂度: O(1)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| class Solution { public ListNode deleteDuplicates(ListNode head) { if (head == null || head.next == null) { return head; } ListNode dummy = new ListNode(0); ListNode curr = head, prev = dummy; dummy.next = head; while (curr != null) { while (curr.next != null && curr.val == curr.next.val) { curr = curr.next; } if (prev.next == curr) { prev = curr; } else { prev.next = curr.next; } curr = curr.next; } return dummy.next; } }
|
这个方法也很好. 就是让curr是否和自己的下一个一样, 如果一样, curr就继续走. 我们需要考虑到curr到达edge case即结尾的时候. 如果curr.next是null的话, 我们访问curr.next.val就是null pointer exception. 于是要加入这个条件即curr.next != null. 此时看prev和curr的相对位置. 如果curr压根没动即prev.next == curr.那么等于是curr下一个值和自己不一样或者下一个值是null, 于是我们让prev = curr即可, 然后更新curr到curr.next. 如果curr移动了, 那说明是找到了一些相同的值. 于是我们让prev.next等于curr.next. 不管curr.next是不同的值还是null, 这样做都是对的. 然后更新curr到curr.next即可.
时间复杂度: O(n)
空间复杂度: O(1)