链表定义:
struct ListNode {
int val;
ListNode* next;
ListNode() : val(0), next(nullptr) {}
ListNode(int x) : val(x), next(nullptr) {}
ListNode(int x, ListNode* next) : val(x), next(next) {}
};
83. 删除排序链表中的重复元素
存在一个按升序排列的链表,给你这个链表的头节点 head ,请你删除所有重复的元素,使每个元素 只出现一次 。
返回同样按升序排列的结果链表。
>>>>>>>>>>>>>>更多细节请看原题>>>>>>>>>>>>>>
提示:
链表中节点数目在范围 [0, 300] 内
-100 <= Node.val <= 100
题目数据保证链表已经按升序排列
递归
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
if (!head || !(head->next))
return head;//节点数不大于1直接返回
if (head->val != head->next->val) {
head->next = deleteDuplicates(head->next);//当前节点未出现重复,与下一个节点连接起来
}
else {
ListNode* move = head->next;
while (move && move->val == head->val) {
move = move->next;
}
//出循环时move位于第一个不重复的元素
head->next = move;//将head与之相连
return deleteDuplicates(head);//继续遍历链表
}
return head;//递归结束返回头结点
}
};
- 一次遍历,时间复杂度O(N)
- 递归造成的最大内存栈深度为 N,空间复杂度O(N)
迭代
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
if (!head) return head;
ListNode* virNode = new ListNode(0, head);
ListNode* curNode = head;
while (curNode->next) {
if (curNode->val == curNode->next->val) {
curNode->next = curNode->next->next;
}
else {
curNode = curNode->next;
}
}
return virNode->next;
}
};
- 一次遍历,时间复杂度O(N)
- 使用指针变量常量空间,空间复杂度O(1)
82. 删除排序链表中的重复元素 II
存在一个按升序排列的链表,给你这个链表的头节点 head ,请你删除链表中所有存在数字重复情况的节点,只保留原始链表中 没有重复出现 的数字。
返回同样按升序排列的结果链表。
>>>>>>>>>>>>>>更多细节请看原题>>>>>>>>>>>>>>
提示:
链表中节点数目在范围 [0, 300] 内
-100 <= Node.val <= 100
题目数据保证链表已经按升序排列
递归
贴上一段“ @负雪明烛 ”大佬对于递归的解析:
【负雪明烛】递归+迭代,一篇题解吃透本题
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
if (!head || !(head->next))
return head;//当节点个数不大于1的时候直接返回,无需操作
if (head->val != head->next->val) {
head->next = deleteDuplicates(head->next);
}
else {
ListNode* move = head->next;
while (move && move->val == head->val) {
move = move->next;
}
//出循环move指向第一个与head不相等的节点
return deleteDuplicates(move);//这里与上一题不同的是直接返回的是move:之前的重复元素都被删除掉了
}
return head;//递归结束,返回头结点
}
};
- 一次遍历,时间复杂度O(N)
- 递归造成的最大内存栈深度为 N,空间复杂度O(N)
迭代
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
ListNode* virNode = new ListNode(0, head);//生成伪节点可避免后面的一些判断
ListNode* prev = virNode;
ListNode* curr = head;
while (curr) {
if (curr->next && curr->val == curr->next->val) {
do {//这块代码希望读者画图理解,写链表题一定要画图模拟遍历过程啊!写链表题一定要画图模拟遍历过程啊!写链表题一定要画图模拟遍历过程啊!重要的话说三遍!!!
curr = curr->next;
} while (curr->next && curr->val == curr->next->val);
prev->next = curr->next;
curr = curr->next;
}
else {
curr = curr->next;
prev = prev->next;
}
}
return virNode->next;
}
};
- 一次遍历,时间复杂度O(N)
- 使用指针变量常量空间,空间复杂度O(1)
持续更新… …