牛客题解 | 删除有序链表中重复的元素-II
1.牛客题解 | N皇后问题2.牛客题解 | 三数之和3.牛客题解 | 三角形最小路径和4.牛客题解 | 不同路径的数目(一)5.牛客题解 | 不用加减乘除做加法6.牛客题解 | 丑数7.牛客题解 | 两个链表的第一个公共结点8.牛客题解 | 两个链表的第一个公共结点_19.牛客题解 | 两数之和10.牛客题解 | 主持人调度(二)11.牛客题解 | 买卖股票的最好时机(一)12.牛客题解 | 买卖股票的最好时机(三)13.牛客题解 | 买卖股票的最好时机(二)14.牛客题解 | 二分查找-I15.牛客题解 | 二叉搜索树与双向链表16.牛客题解 | 二叉搜索树的后序遍历序列17.牛客题解 | 二叉搜索树的最近公共祖先18.牛客题解 | 二叉搜索树的第k个节点19.牛客题解 | 二叉树中和为某一值的路径(一)20.牛客题解 | 二叉树中和为某一值的路径(三)21.牛客题解 | 二叉树中和为某一值的路径(二)22.牛客题解 | 二叉树的下一个结点23.牛客题解 | 二叉树的中序遍历24.牛客题解 | 二叉树的前序遍历25.牛客题解 | 二叉树的后序遍历26.牛客题解 | 二叉树的最大深度27.牛客题解 | 二叉树的深度28.牛客题解 | 二叉树的镜像29.牛客题解 | 二维数组中的查找30.牛客题解 | 二维数组中的查找_131.牛客题解 | 二进制中1的个数32.牛客题解 | 从上往下打印二叉树33.牛客题解 | 从中序与后序遍历序列构造二叉树34.牛客题解 | 从尾到头打印链表35.牛客题解 | 兑换零钱(一)36.牛客题解 | 分糖果问题37.牛客题解 | 删除有序链表中重复的元素-I
38.牛客题解 | 删除有序链表中重复的元素-II
39.牛客题解 | 删除链表中重复的结点40.牛客题解 | 删除链表中重复的结点41.牛客题解 | 删除链表的倒数第n个节点42.牛客题解 | 删除链表的节点43.牛客题解 | 判断一个链表是否为回文结构44.牛客题解 | 判断是不是二叉搜索树45.牛客题解 | 判断是不是完全二叉树46.牛客题解 | 判断是不是平衡二叉树47.牛客题解 | 判断是不是平衡二叉树_148.牛客题解 | 判断是否为回文字符串49.牛客题解 | 判断链表中是否有环50.牛客题解 | 剪绳子51.牛客题解 | 剪绳子(进阶版)52.牛客题解 | 包含min函数的栈53.牛客题解 | 包含min函数的栈_154.牛客题解 | 单链表的排序55.牛客题解 | 反转字符串56.牛客题解 | 反转链表57.牛客题解 | 反转链表_158.牛客题解 | 反转链表_259.牛客题解 | 合并k个已排序的链表60.牛客题解 | 合并两个排序的链表61.牛客题解 | 合并两个排序的链表_162.牛客题解 | 合并两个有序的数组63.牛客题解 | 合并二叉树64.牛客题解 | 合并区间65.牛客题解 | 和为S的两个数字66.牛客题解 | 和为S的连续正数序列67.牛客题解 | 在二叉树中找到两个节点的最近公共祖先68.牛客题解 | 复杂链表的复制69.牛客题解 | 多数组中位数70.牛客题解 | 多数组第 K 小数71.牛客题解 | 大数加法72.牛客题解 | 字符串变形73.牛客题解 | 字符串的排列74.牛客题解 | 字符串的排列_175.牛客题解 | 字符流中第一个不重复的字符76.牛客题解 | 孩子们的游戏(圆圈中最后剩下的数)77.牛客题解 | 实现二叉树先序,中序和后序遍历78.牛客题解 | 对称的二叉树79.牛客题解 | 对称的二叉树_180.牛客题解 | 寻找峰值81.牛客题解 | 寻找第K大82.牛客题解 | 小米Git83.牛客题解 | 岛屿数量84.牛客题解 | 接雨水问题85.牛客题解 | 数值的整数次方86.牛客题解 | 数字在升序数组中出现的次数87.牛客题解 | 数字字符串转化成IP地址88.牛客题解 | 数字序列中某一位的数字89.牛客题解 | 数据流中的中位数90.牛客题解 | 数据流中的中位数_191.牛客题解 | 数组中出现次数超过一半的数字92.牛客题解 | 数组中出现次数超过一半的数字_193.牛客题解 | 数组中只出现一次的两个数字94.牛客题解 | 数组中的逆序对95.牛客题解 | 数组中的逆序对_196.牛客题解 | 数组中重复的数字97.牛客题解 | 整数中1出现的次数(从1到n整数中1出现的次数)98.牛客题解 | 斐波那契数列99.牛客题解 | 斐波那契数列_1100.牛客题解 | 旋转数组题目
题目的主要信息:
- 在一个非降序的链表中,存在重复的节点,删除该链表中重复的节点
- 重复的节点一个元素也不保留
举一反三:
学习完本题的思路你可以解决如下题目:
方法一:直接比较删除(推荐使用)
思路:
这是一个升序链表,重复的节点都连在一起,我们就可以很轻易地比较到重复的节点,然后将所有的连续相同的节点都跳过,连接不相同的第一个节点。
//遇到相邻两个节点值相同
if(cur.next.val == cur.next.next.val){
int temp = cur.next.val;
//将所有相同的都跳过
while (cur.next != null && cur.next.val == temp)
cur.next = cur.next.next;
}
具体做法:
- step 1:给链表前加上表头,方便可能的话删除第一个节点。
ListNode res = new ListNode(0);
//在链表前加一个表头
res.next = head;
- step 2:遍历链表,每次比较相邻两个节点,如果遇到了两个相邻节点相同,则新开内循环将这一段所有的相同都遍历过去。
- step 3:在step 2中这一连串相同的节点前的节点直接连上后续第一个不相同值的节点。
- step 4:返回时去掉添加的表头。
图示:
Java实现代码:
import java.util.*;
public class Solution {
public ListNode deleteDuplicates (ListNode head) {
//空链表
if(head == null)
return null;
ListNode res = new ListNode(0);
//在链表前加一个表头
res.next = head;
ListNode cur = res;
while(cur.next != null && cur.next.next != null){
//遇到相邻两个节点值相同
if(cur.next.val == cur.next.next.val){
int temp = cur.next.val;
//将所有相同的都跳过
while (cur.next != null && cur.next.val == temp)
cur.next = cur.next.next;
}
else
cur = cur.next;
}
//返回时去掉表头
return res.next;
}
}
C++实现代码:
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
//空链表
if(head == NULL)
return NULL;
ListNode* res = new ListNode(0);
//在链表前加一个表头
res->next = head;
ListNode* cur = res;
while(cur->next != NULL && cur->next->next != NULL){
//遇到相邻两个节点值相同
if(cur->next->val == cur->next->next->val){
int temp = cur->next->val;
//将所有相同的都跳过
while (cur->next != NULL && cur->next->val == temp)
cur->next = cur->next->next;
}
else
cur = cur->next;
}
//返回时去掉表头
return res->next;
}
};
Phthon实现代码:
class Solution:
def deleteDuplicates(self , head: ListNode) -> ListNode:
#空链表
if head == None:
return None
res = ListNode(0)
#在链表前加一个表头
res.next = head
cur = res
while cur.next and cur.next.next:
#遇到相邻两个节点值相同
if cur.next.val == cur.next.next.val:
temp = cur.next.val
#将所有相同的都跳过
while cur.next != None and cur.next.val == temp:
cur.next = cur.next.next
else:
cur = cur.next
#返回时去掉表头
return res.next
复杂度分析:
- 时间复杂度:,其中为链表节点数,只有一次遍历
- 空间复杂度:,只开辟了临时指针,常数级空间
方法二:哈希表(扩展思路)
知识点:哈希表
哈希表是一种根据关键码(key)直接访问值(value)的一种数据结构。而这种直接访问意味着只要知道key就能在时间内得到value,因此哈希表常用来统计频率、快速检验某个元素是否出现过等。
思路:
这道题幸运的是链表有序,我们可以直接与旁边的元素比较,然后删除重复。那我们扩展一点,万一遇到的链表无序呢?我们这里给出一种通用的解法,有序无序都可以使用,即利用哈希表来统计是否重复。
具体做法:
- step 1:遍历一次链表用哈希表记录每个节点值出现的次数。
- step 2:在链表前加一个节点值为0的表头,方便可能的话删除表头元素。
- step 3:再次遍历该链表,对于每个节点值检查哈希表中的计数,只留下计数为1的,其他情况都删除。
- step 4:返回时去掉增加的表头。
Java实现代码:
import java.util.*;
public class Solution {
public ListNode deleteDuplicates (ListNode head) {
//空链表
if(head == null)
return null;
Map<Integer,Integer> mp = new HashMap<>();
ListNode cur = head;
//遍历链表统计每个节点值出现的次数
while(cur != null){
if(mp.containsKey(cur.val))
mp.put(cur.val, (int)mp.get(cur.val) + 1);
else
mp.put(cur.val,1);
cur = cur.next;
}
ListNode res = new ListNode(0);
//在链表前加一个表头
res.next = head;
cur = res;
//再次遍历链表
while(cur.next != null){
//如果节点值计数不为1
if(mp.get(cur.next.val) != 1)
//删去该节点
cur.next = cur.next.next;
else
cur = cur.next;
}
//去掉表头
return res.next;
}
}
C++实现代码:
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
//空链表
if(head == NULL)
return NULL;
unordered_map<int, int> mp;
ListNode* cur = head;
//遍历链表统计每个节点值出现的次数
while(cur != NULL){
mp[cur->val]++;
cur = cur->next;
}
ListNode* res = new ListNode(0);
//在链表前加一个表头
res->next = head;
cur = res;
//再次遍历链表
while(cur->next != NULL){
//如果节点值计数不为1
if(mp[cur->next->val] != 1)
//删去该节点
cur->next = cur->next->next;
else
cur = cur->next;
}
//去掉表头
return res->next;
}
};
Python实现代码:
class Solution:
def deleteDuplicates(self , head: ListNode) -> ListNode:
#空链表
if head == None:
return None
mp = dict()
cur = head
#遍历链表统计每个节点值出现的次数
while cur:
if cur.val in mp:
mp[cur.val] += 1
else:
mp[cur.val] = 1
cur = cur.next
res = ListNode(0)
#在链表前加一个表头
res.next = head
cur = res
#再次遍历链表
while cur.next:
#如果节点值计数不为1
if mp[cur.next.val] != 1:
#删去该节点
cur.next = cur.next.next
else:
cur = cur.next
#去掉表头
return res.next
复杂度分析:
- 时间复杂度:,其中为链表节点数,一共两次遍历,哈希表每次计数、每次查询都是
- 空间复杂度:,最坏情况下个节点都不相同,哈希表长度为
合集:
牛客面试高频题单题解
分类:
牛客面试高频题单题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理