给定一个已排序的链表的头 head
, 删除原始链表中所有重复数字的节点,只留下不同的数字 。返回 已排序的链表 。
示例 1:
**输入:** head = [1,2,3,3,4,4,5]
**输出:** [1,2,5]
示例 2:
**输入:** head = [1,1,1,2,3]
**输出:** [2,3]
提示:
链表中节点数目在范围 [0, 300]
内
-100 <= Node.val <= 100
题目数据保证链表已经按升序 排列
方法一:一次遍历 思路与算法
由于给定的链表是排好序的,因此重复的元素在链表中出现的位置是连续的 ,因此我们只需要对链表进行一次遍历,就可以删除重复的元素。由于链表的头节点可能会被删除,因此我们需要额外使用一个哑节点(dummy node)指向链表的头节点。
具体地,我们从指针 $\textit{cur}$ 指向链表的哑节点,随后开始对链表进行遍历。如果当前 $\textit{cur.next}$ 与 $\textit{cur.next.next}$ 对应的元素相同,那么我们就需要将 $\textit{cur.next}$ 以及所有后面拥有相同元素值的链表节点全部删除。我们记下这个元素值 $x$,随后不断将 $\textit{cur.next}$ 从链表中移除,直到 $\textit{cur.next}$ 为空节点或者其元素值不等于 $x$ 为止。此时,我们将链表中所有元素值为 $x$ 的节点全部删除。
如果当前 $\textit{cur.next}$ 与 $\textit{cur.next.next}$ 对应的元素不相同,那么说明链表中只有一个元素值为 $\textit{cur.next}$ 的节点,那么我们就可以将 $\textit{cur}$ 指向 $\textit{cur.next}$。
当遍历完整个链表之后,我们返回链表的的哑节点的下一个节点 $\textit{dummy.next}$ 即可。
细节
需要注意 $\textit{cur.next}$ 以及 $\textit{cur.next.next}$ 可能为空节点,如果不加以判断,可能会产生运行错误。
代码
注意下面 $\texttt{C++}$ 代码中并没有释放被删除的链表节点以及哑节点的空间。如果在面试中遇到本题,读者需要针对这一细节与面试官进行沟通。
[sol1-C++] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class Solution {public : ListNode* deleteDuplicates (ListNode* head) { if (!head) { return head; } ListNode* dummy = new ListNode (0 , head); ListNode* cur = dummy; while (cur->next && cur->next->next) { if (cur->next->val == cur->next->next->val) { int x = cur->next->val; while (cur->next && cur->next->val == x) { cur->next = cur->next->next; } } else { cur = cur->next; } } return dummy->next; } };
[sol1-Java] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Solution { public ListNode deleteDuplicates (ListNode head) { if (head == null ) { return head; } ListNode dummy = new ListNode (0 , head); ListNode cur = dummy; while (cur.next != null && cur.next.next != null ) { if (cur.next.val == cur.next.next.val) { int x = cur.next.val; while (cur.next != null && cur.next.val == x) { cur.next = cur.next.next; } } else { cur = cur.next; } } return dummy.next; } }
[sol1-Python3] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Solution : def deleteDuplicates (self, head: ListNode ) -> ListNode: if not head: return head dummy = ListNode(0 , head) cur = dummy while cur.next and cur.next .next : if cur.next .val == cur.next .next .val: x = cur.next .val while cur.next and cur.next .val == x: cur.next = cur.next .next else : cur = cur.next return dummy.next
[sol1-JavaScript] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 var deleteDuplicates = function (head ) { if (!head) { return head; } const dummy = new ListNode (0 , head); let cur = dummy; while (cur.next && cur.next .next ) { if (cur.next .val === cur.next .next .val ) { const x = cur.next .val ; while (cur.next && cur.next .val === x) { cur.next = cur.next .next ; } } else { cur = cur.next ; } } return dummy.next ; };
[sol1-Golang] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 func deleteDuplicates (head *ListNode) *ListNode { if head == nil { return nil } dummy := &ListNode{0 , head} cur := dummy for cur.Next != nil && cur.Next.Next != nil { if cur.Next.Val == cur.Next.Next.Val { x := cur.Next.Val for cur.Next != nil && cur.Next.Val == x { cur.Next = cur.Next.Next } } else { cur = cur.Next } } return dummy.Next }
[sol1-C] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 struct ListNode* deleteDuplicates (struct ListNode* head) { if (!head) { return head; } struct ListNode * dummy = malloc (sizeof (struct ListNode)); dummy->next = head; struct ListNode * cur = dummy; while (cur->next && cur->next->next) { if (cur->next->val == cur->next->next->val) { int x = cur->next->val; while (cur->next && cur->next->val == x) { cur->next = cur->next->next; } } else { cur = cur->next; } } return dummy->next; }
复杂度分析