目录
问题描述
示例1
示例2
解题思路
代码实现
代码解析
1. 初始化
2. 遍历链表
总结
问题描述
给出一个升序排序的链表,删除链表中的所有重复出现的元素,只保留原链表中只出现一次的元素。
例如:
给出的链表为1→2→3→3→4→4→51→2→3→3→4→4→5, 返回1→2→51→2→5.
给出的链表为1→1→1→2→31→1→1→2→3, 返回2→32→3.
数据范围:链表长度 0≤n≤100000≤n≤10000,链表中的值满足 ∣val∣≤1000∣val∣≤1000
要求:空间复杂度 O(n)O(n),时间复杂度 O(n)O(n)
进阶:空间复杂度 O(1)O(1),时间复杂度 O(n)O(n)
示例1
输入:
{1,2,2}
返回值:
{1}
示例2
输入:
{}
返回值:
{}
解题思路
首先,创建一个虚拟头节点 pre
,并初始化一个指针 p
用于追踪新链表的尾部,指针 cur
用于遍历原链表。然后,使用 cur
指针遍历链表,当遇到 cur
和 cur->next
节点值相等时,说明存在重复元素,继续移动 cur
指针跳过所有重复的节点,直到找到一个不同的节点。如果没有重复元素,则将当前节点 cur
加入新链表,并更新指针 p
。这个过程会一直执行,直到遍历完整个链表。最后,返回虚拟头节点 pre
后的节点,构成去重后的链表。
代码实现
ListNode* deleteDuplicates(ListNode* head) {
// write code here
ListNode* pre = new ListNode(-1);
ListNode* p = pre;
ListNode* cur = head;
while(cur != nullptr)
{
if(cur->next != nullptr && cur->val == cur->next->val)
{
while(cur->next != nullptr && cur->val == cur->next->val)
{
cur = cur->next;
}
cur = cur->next;
if(cur == nullptr) p->next = nullptr;
}
else {
p->next = cur;
cur = cur->next;
p = p->next;
}
}
return pre->next;
}
代码解析
1. 初始化
ListNode* pre = new ListNode(-1);
ListNode* p = pre;
ListNode* cur = head;
创建虚拟头节点,并初始化指针。p
用于构建新的链表,初始指向虚拟头节点 pre
。cur
用于遍历原链表,初始指向输入链表的头节点 head
。
2. 遍历链表
while(cur != nullptr)
{
if(cur->next != nullptr && cur->val == cur->next->val)
{
while(cur->next != nullptr && cur->val == cur->next->val)
{
cur = cur->next;
}
cur = cur->next;
if(cur == nullptr) p->next = nullptr;
}
else {
p->next = cur;
cur = cur->next;
p = p->next;
}
}
while
循环用于遍历链表,直到 cur
指向 nullptr
,即遍历到链表的末尾为止。当当前节点的值与下一个节点的值相等时,说明遇到重复的元素。此时,跳过所有值相同的重复节点,直到遇到一个不同的节点,跳过重复节点后,将 cur
移动到下一个节点,继续遍历。如果当前节点没有重复(即 cur->val != cur->next->val
),则将当前节点 cur
加入新的链表,更新 p
指针指向当前节点,并将 cur
移动到下一个节点。
总结
代码通过遍历排序链表,删除所有重复的节点,保留唯一的元素。使用一个虚拟头节点简化链表操作,并用两个指针 cur
和 p
分别负责遍历原链表和构建去重后的新链表。当遇到重复节点时,跳过所有重复元素,直到找到一个不同的节点,继续将其添加到新链表中。最终返回去重后的链表。