删除排序链表中的重复元素系列

这篇博客介绍了如何删除排序链表中的重复元素,提供了两种方法:递归和迭代。递归方法在遇到重复元素时会跳过,而迭代方法通过伪节点避免了额外判断。两种方法的时间复杂度均为O(N),但递归方法可能造成O(N)的空间复杂度,而迭代方法则保持在O(1)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

链表定义:

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)
    在这里插入图片描述
    持续更新… …
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

nepu_bin

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值