输入: 一个已排序的单链表的头节点 head。
要求: 删除原始链表中所有具有重复数字的节点,只留下不同的数字。返回已排序的链表。
输出: 删除所有重复项后,已排序的链表头节点。
思路:虚拟头节点 + 三指针
这道题的关键在于,一个节点是否应该被保留,取决于它的后一个节点的值是否与它相同。使用虚拟头节点 dummy 来统一处理头节点可能被删除的情况。
-
定义三个指针:
nodea作为结果链表的尾指针,初始指向dummy;nodeb作为当前待考察的节点;nodec作为nodeb的下一个节点,用于判断nodeb是否重复。 -
循环以
nodeb是否存在为条件。在循环中,判断nodeb是否是一个独特的节点。 -
如果
nodeb的下一个节点nodec不存在,或者nodec的值与nodeb不同,说明nodeb是一个独特的节点,应该被保留。此时,将nodea连接到nodeb,然后nodea和nodeb一同前进。 -
如果
nodeb的下一个节点nodec的值与nodeb相同,说明nodeb是一个重复节点,必须被删除。此时nodea保持不动,我们用一个内部循环跳过所有与nodeb值相同的节点,然后将nodeb直接指向下一个不同的节点,进入下一轮考察。
复杂度:
-
时间复杂度: O(n)
-
空间复杂度: O(1)
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
ListNode* dummy = new ListNode(-1, head);
ListNode* nodea;//每一轮开始的起点 自身是绝对安全的
ListNode* nodeb;//待考察点 需要考察后续的点是否跟本点相同
ListNode* nodec;//前哨点 从待考察点出发 到 空节点之前或者下一个待考察点之前
nodea = dummy;//很安全
nodeb = dummy->next;
while (nodeb) { //如果待考察点依旧存在就继续考察 如果不存在了 那确实该结束了
nodec = nodeb->next;//开始对nodeb考察
if (!nodec || nodec->val != nodeb->val) {//考察成功 要么后面没有 要么不等
nodea->next = nodeb;
nodea = nodeb;
nodeb = nodec;
}
else {
while (nodec->next && nodec->next->val == nodeb->val) {
nodec = nodec->next;
}
if (!nodec->next) {
nodea->next = nullptr;
nodeb = nullptr;
}
else {
nodeb = nodec->next;
}
}
}
return dummy->next;
}
};
1655

被折叠的 条评论
为什么被折叠?



