Remove Duplicates from Unsorted List

Question

  1. Write a removeDuplicates() function which takes a list and deletes
  2. any duplicate nodes from the list. The list is not sorted.
  3. For example if the linked list is 12->11->12->21->41->43->21,
  4. then removeDuplicates() should convert the list to 12->11->21->41->43.
  5. If temporary buffer is not allowed, how to solve it?

题解1 - 两重循环

Remove Duplicates 系列题,之前都是已排序链表,这个题为未排序链表。原题出自 CTCI 题2.1。

最容易想到的简单办法就是两重循环删除重复节点了,当前遍历节点作为第一重循环,当前节点的下一节点作为第二重循环。

Python

  1. """
  2. Definition of ListNode
  3. class ListNode(object):
  4. def __init__(self, val, next=None):
  5. self.val = val
  6. self.next = next
  7. """
  8. class Solution:
  9. """
  10. @param head: A ListNode
  11. @return: A ListNode
  12. """
  13. def deleteDuplicates(self, head):
  14. if head is None:
  15. return None
  16. curr = head
  17. while curr is not None:
  18. inner = curr
  19. while inner.next is not None:
  20. if inner.next.val == curr.val:
  21. inner.next = inner.next.next
  22. else:
  23. inner = inner.next
  24. curr = curr.next
  25. return head

C++

  1. /**
  2. * Definition of ListNode
  3. * class ListNode {
  4. * public:
  5. * int val;
  6. * ListNode *next;
  7. * ListNode(int val) {
  8. * this->val = val;
  9. * this->next = NULL;
  10. * }
  11. * }
  12. */
  13. class Solution {
  14. public:
  15. /**
  16. * @param head: The first node of linked list.
  17. * @return: head node
  18. */
  19. ListNode *deleteDuplicates(ListNode *head) {
  20. if (head == NULL) return NULL;
  21. ListNode *curr = head;
  22. while (curr != NULL) {
  23. ListNode *inner = curr;
  24. while (inner->next != NULL) {
  25. if (inner->next->val == curr->val) {
  26. inner->next = inner->next->next;
  27. } else {
  28. inner = inner->next;
  29. }
  30. }
  31. curr = curr->next;
  32. }
  33. return head;
  34. }
  35. };

Java

  1. /**
  2. * Definition for ListNode
  3. * public class ListNode {
  4. * int val;
  5. * ListNode next;
  6. * ListNode(int x) {
  7. * val = x;
  8. * next = null;
  9. * }
  10. * }
  11. */
  12. public class Solution {
  13. /**
  14. * @param ListNode head is the head of the linked list
  15. * @return: ListNode head of linked list
  16. */
  17. public static ListNode deleteDuplicates(ListNode head) {
  18. if (head == null) return null;
  19. ListNode curr = head;
  20. while (curr != null) {
  21. ListNode inner = curr;
  22. while (inner.next != null) {
  23. if (inner.next.val == curr.val) {
  24. inner.next = inner.next.next;
  25. } else {
  26. inner = inner.next;
  27. }
  28. }
  29. curr = curr.next;
  30. }
  31. return head;
  32. }
  33. }

源码分析

删除链表的操作一般判断node.next较为合适,循环时注意inner = inner.nextinner.next = inner.next.next的区别即可。

复杂度分析

两重循环,时间复杂度为 O(\frac{1}{2}n^2), 空间复杂度近似为 O(1).

题解2 - 万能的 hashtable

使用辅助空间哈希表,节点值作为键,布尔值作为相应的值(是否为布尔值其实无所谓,关键是键)。

Python

  1. """
  2. Definition of ListNode
  3. class ListNode(object):
  4. def __init__(self, val, next=None):
  5. self.val = val
  6. self.next = next
  7. """
  8. class Solution:
  9. """
  10. @param head: A ListNode
  11. @return: A ListNode
  12. """
  13. def deleteDuplicates(self, head):
  14. if head is None:
  15. return None
  16. hash = {}
  17. hash[head.val] = True
  18. curr = head
  19. while curr.next is not None:
  20. if hash.has_key(curr.next.val):
  21. curr.next = curr.next.next
  22. else:
  23. hash[curr.next.val] = True
  24. curr = curr.next
  25. return head

C++

  1. /**
  2. * Definition of ListNode
  3. * class ListNode {
  4. * public:
  5. * int val;
  6. * ListNode *next;
  7. * ListNode(int val) {
  8. * this->val = val;
  9. * this->next = NULL;
  10. * }
  11. * }
  12. */
  13. class Solution {
  14. public:
  15. /**
  16. * @param head: The first node of linked list.
  17. * @return: head node
  18. */
  19. ListNode *deleteDuplicates(ListNode *head) {
  20. if (head == NULL) return NULL;
  21. // C++ 11 use unordered_map
  22. // unordered_map<int, bool> hash;
  23. map<int, bool> hash;
  24. hash[head->val] = true;
  25. ListNode *curr = head;
  26. while (curr->next != NULL) {
  27. if (hash.find(curr->next->val) != hash.end()) {
  28. ListNode *temp = curr->next;
  29. curr->next = curr->next->next;
  30. delete temp;
  31. } else {
  32. hash[curr->next->val] = true;
  33. curr = curr->next;
  34. }
  35. }
  36. return head;
  37. }
  38. };

Java

  1. /**
  2. * Definition for ListNode
  3. * public class ListNode {
  4. * int val;
  5. * ListNode next;
  6. * ListNode(int x) {
  7. * val = x;
  8. * next = null;
  9. * }
  10. * }
  11. */
  12. public class Solution {
  13. /**
  14. * @param ListNode head is the head of the linked list
  15. * @return: ListNode head of linked list
  16. */
  17. public static ListNode deleteDuplicates(ListNode head) {
  18. if (head == null) return null;
  19. ListNode curr = head;
  20. HashMap<Integer, Boolean> hash = new HashMap<Integer, Boolean>();
  21. hash.put(curr.val, true);
  22. while (curr.next != null) {
  23. if (hash.containsKey(curr.next.val)) {
  24. curr.next = curr.next.next;
  25. } else {
  26. hash.put(curr.next.val, true);
  27. curr = curr.next;
  28. }
  29. }
  30. return head;
  31. }
  32. }

源码分析

删除链表中某个节点的经典模板在while循环中体现。

复杂度分析

遍历一次链表,时间复杂度为 O(n), 使用了额外的哈希表,空间复杂度近似为 O(n).

Reference