删除链表中重复的节点(五十六)

题目描述:

在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。 例如,链表1->2->3->3->4->4->5 处理后为 1->2->5

代码(已在牛客上 AC)

在判断是否有重复值时, 用了一种看起来有点冗余的写法, 在 ​​if (p->next && p->next->val == p->val)​​​ 对重复值进行判断之后, 然后又在 ​​while (pn && pn->val == p->val)​​​ 做了同样的判断, 但是感觉这样写, 代码容易读一点. 最后 ​​pn​​​ 指向某个与 ​​p->val​​​ 不同的值, 或者直接为空, 都没有关系, 令 ​​p = pn​​​, 然后 ​​continue​​ 进行新一轮的判断即可.

class Solution {
public:
ListNode* deleteDuplication(ListNode *root) {
if (!root || !root->next) return root;
auto p = root;
ListNode *dummy = new ListNode(0);
auto ptr = dummy;

while (p) {
if (p->next && p->next->val == p->val) {
auto pn = p->next;
while (pn && pn->val == p->val) pn = pn->next;
p = pn;
continue;
}
ptr->next = p;
ptr = ptr->next;
p = p->next;
}
// 注意这一步不能忘记, 最后要将结尾置为空. 比如
// {1, 2, 5, 5}, 最后 ptr 是指向 2 的, 如果
// 不设置结尾为空, 会把后面两个 5 给带上...
ptr->next = nullptr;
return dummy->next;
}
};

另一种写法, 也 AC, 但是呢, 写的年代有点久远了, 当初没写个注释, 现在不愿花时间再看了…

class Solution {
public:
ListNode* deleteDuplication(ListNode* root) {
if (!root || !root->next) return root;
ListNode *dummy = new ListNode(0);
ListNode *k = dummy;
ListNode *prev = root, *ptr = prev->next;
int value = root->val;
while (ptr) {
if (ptr->val == value) ptr = ptr->next;
else {
if (prev->next == ptr) {
k->next = prev;
k = k->next;
}
prev = ptr;
value = prev->val;
ptr = prev->next;
}
}
k->next = prev->next ? nullptr : prev;
return dummy->next;
}
};