给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现 的数字。

输入: 1->2->3->3->4->4->5 输出: 1->2->5
输入: 1->1->1->2->3 输出: 2->3
dummy
方法一:一次遍历
思路与算法
由于给定的链表是排好序的,因此重复的元素在链表中出现的位置是连续的,因此我们只需要对链表进行一次遍历,就可以删除重复的元素。由于链表的头节点可能会被删除,因此我们需要额外使用一个哑节点(dummy node)指向链表的头节点。
具体地,我们从指针 \textit{cur}cur 指向链表的哑节点,随后开始对链表进行遍历。如果当前 \textit{cur.next}cur.next 与 \textit{cur.next.next}cur.next.next 对应的元素相同,那么我们就需要将 \textit{cur.next}cur.next 以及所有后面拥有相同元素值的链表节点全部删除。我们记下这个元素值 xx,随后不断将 \textit{cur.next}cur.next 从链表中移除,直到 \textit{cur.next}cur.next 为空节点或者其元素值不等于 xx 为止。此时,我们将链表中所有元素值为 xx 的节点全部删除。
如果当前 \textit{cur.next}cur.next 与 \textit{cur.next.next}cur.next.next 对应的元素不相同,那么说明链表中只有一个元素值为 \textit{cur.next}cur.next 的节点,那么我们就可以将 \textit{cur}cur 指向 \textit{cur.next}cur.next。
当遍历完整个链表之后,我们返回链表的的哑节点的下一个节点 \textit{dummy.next}dummy.next 即可。
细节
需要注意 \textit{cur.next}cur.next 以及 \textit{cur.next.next}cur.next.next 可能为空节点,如果不加以判断,可能会产生运行错误。
代码
注意下面 C++ 代码中并没有释放被删除的链表节点以及哑节点的空间。如果在面试中遇到本题,读者需要针对这一细节与面试官进行沟通。
const deleteDuplicates = function (head) {if (head === null || head.next === null) {return head;}const dummy = new ListNode(-1);dummy.next = head;let cur = dummy;while (cur.next !== null && cur.next.next !== null) {if (cur.next.val === cur.next.next.val) {const repeatVal = cur.next.val;// 每次删除一个cur.next就行了,剩下的后面再删除,// 不用一次删除很多个while(cur.next && cur.next.val === repeatVal) {cur.next = cur.next.next;}} else {cur = cur.next;}}return dummy.next;};
