LeetCode 82,考察你的基本功,在有序链表中删除重复元素II
本文始发于个人公众号:TechFlow,原创不易,求个关注
今天是LeetCode专题的第51篇文章,我们来看LeetCode第82题,删除有序链表中的重复元素II(Remove Duplicates from Sorted List II)。
这题官方给出的难度是Medium,点赞1636,反对107,通过率在36.3%左右。根据我们之前的分析,这题的难度适中,并且质量很高,好评如潮。实际上也的确如此,这题算法本身并不难,但是想要完整没有bug地实现并不容易,我们一起来看看。
题意
给定一个有序的存在重复元素的链表,要求移除掉链表当中所有的重复元素。返回一个不包含重复元素的链表。
这里要注意的一点,这题让我们做的事情并不是去重,就是去除掉多余的元素,而是要去除掉所有重复的元素。比如2在链表当中出现了两次,属于重复元素,我们要做的并不是去掉一个2,仅保留一个,而是要将所有的2都去除,因为2属于重复元素。
我们来看样例:
Input: 1->2->3->3->4->4->5
Output: 1->2->5
原链表当中的3和4都属于重复元素,所以被去除了。
Input: 1->1->1->2->3
Output: 2->3
解法
前面说了这题的质量很高,这题是属于典型的解法赤裸裸,但是很多人就是写不出来的题,非常考察基本功。适合用在校招面试当中,如果我有幸去面试校招生, 我可能会选这道题。不存在算法会不会的问题,写不出来一定是基本功不够扎实。
链表已经有序了,那么相同的元素必然会排在一起,我们只需要将它们移除就可以了。但是说起来简单,要在链表当中实现并不容易。难点主要有两个,一个是链表增删节点的操作很多人不熟悉,尤其是像是C++这样的语言涉及指针,可能更不容易。另外一个难点就在题意当中,我们要做的不是去重,而是要所有重复的元素全部删除。
看起来似乎和去重没什么差别, 如果你真这么想,并且着手去实现,那么几乎可以肯定一定会遇到问题。
因为链表是单向的,假设你当前的指针是cur,当你发现cur这个指针的元素存在重复的时候,你需要连当前这个节点一起删除。我们都知道,单向链表是不能走回头路的,而删除节点,必须要用到前一个节点的指针。再加上判断元素重复需要用到的指针,会需要我们同时维护多个指针,增加代码的编码难度。
针对这个问题,我们有两种解决思路。第一种是我们不在原链表上处理,而是创建一个新的链表进行返回。所以我们要做的就不是删除元素,而是插入元素,只有发现当前元素不存在重复的时候才会插入链表。最后返回的也是一个全新的链表。
这当然是可以的,也是没有问题了,我第一次做这道题就是采取的这种措施。相比之下, 这种方法会容易一些,因为我们不需要判断太多的指针和位置,我贴一下当时的代码:
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
// 如果元素少于2个则直接返回
if (head == nullptr || head->next == nullptr) return head;
int cur = head->val;
// 初始化
bool flag = false;
ListNode* ct = new ListNode(0);
ListNode* pnt = ct;
head = head->next;
// 遍历元素
while (head) {
int hd = head->val;
// 判断当前元素与之前的元素是否相等
if (hd != cur) {
// 之前的元素没有出现重复
if (!flag) {
// 把之前的元素存入链表
pnt->next = new ListNode(cur);
// 链表移动
pnt = pnt->next;
}else flag = false;
// 更新之前的元素
cur = hd;
}else flag = true;
head = head->next;
}
// 单独处理最后一个元素
if (!flag) pnt->next = new ListNode(cur);
return ct->next;
}
};
虽然题目当中没有对解法做出限制,也没有规定我们必须要在原链表上进行处理,但是这种创建新链表的方法终归有绕开问题的嫌疑。所以我们还有第二种解法,就是直面问题,我们维护多个指针,判断当前位置的下一个元素是否构成重复。如果重复,则删除掉重复的部分。
正如我们之前所说的那样,在单向链表当中很难删除当前元素,所以我们判断下一个元素是否会构成重复。如果重复的话,进行删除要可行许多。这样也有一个问题就是,有可能链表的第一个元素就是重复的,我们没有办法找到第一个元素的上一个元素。针对这个问题,我们采用的方法是人为给它创造一个元素放在首元素之前。这样我们整个流程就可以串起来了,唯一的难点就是编码了。
我们仔细一些,写出代码还是可以的:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def deleteDuplicates(self, head: ListNode) -> ListNode:
# 创建一个新的元素放在链表头部,这样原本第一个元素就是头指针的下一个元素了
node = ListNode()
node.next = head
# pnt指向新创建的元素
pnt = node
while pnt.next is not None:
# cur指向当前位置的下一个位置
# 我们要做的即判断cur这个指针的元素是否重复
cur = pnt.next
if cur.next is None:
break
# ptr指向cur的next
ptr = cur.next
# 如果ptr和cur相等,那么出现重复,我们需要跳过所有相等的元素
if ptr is not None and ptr.val == cur.val:
while ptr is not None and ptr.val == cur.val:
ptr = ptr.next
pnt.next = ptr
# 否则说明不重复,移动pnt
else:
pnt = pnt.next
# 由于我们开始的时候人为添加了一个辅助元素
# 返回的时候要将它去除
return node.next
总结
这道题的算法很简单,我想大部分人都能想出解法来,但是要将解法实现并不太容易。这当中用到了很多小技巧,比如我们认为创建了一个新的头结点,比如我们将删除当前元素转化成了删除下一个元素等等。这些技巧虽然算不上什么,但是灵活使用,可以大大降低我们编码的复杂度,也正是因为这一点,这题的质量非常高,值得一做。
很多人非常讨厌涉及链表的问题,觉得链表很难操作,容易写错,但实际上这是基本功的很重要的一部分。很多公司喜欢考察候选人的基本功,提升这方面的能力对于我们应聘或者是工作非常有帮助。
今天的文章到这里就结束了,如果喜欢本文的话,请来一波素质三连,给我一点支持吧(关注、转发、点赞)。
本文使用 mdnice 排版
LeetCode 82,考察你的基本功,在有序链表中删除重复元素II的更多相关文章
- LeetCode 82. 删除排序链表中的重复元素 II(Remove Duplicates from Sorted List II)
82. 删除排序链表中的重复元素 II 82. Remove Duplicates from Sorted List II 题目描述 给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中没有 ...
- LeetCode 83. Remove Duplicates from Sorted List(从有序链表中删除重复节点)
题意:从有序链表中删除重复节点. /** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode ...
- Java实现 LeetCode 82 删除排序链表中的重复元素 II(二)
82. 删除排序链表中的重复元素 II 给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现 的数字. 示例 1: 输入: 1->2->3->3->4- ...
- leetcode 83. 删除排序链表中的重复元素 及 82. 删除排序链表中的重复元素 II
83. 删除排序链表中的重复元素 问题描述 给定一个排序链表,删除所有重复的元素,使得每个元素只出现一次. 示例 1: 输入: 1->1->2 输出: 1->2 示例 2: 输入: ...
- [LeetCode] 82. Remove Duplicates from Sorted List II 移除有序链表中的重复项 II
Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numb ...
- 力扣(LeetCode)删除排序链表中的重复元素II 个人题解
给定一个排序链表,删除所有含有重复数字的节点,只保留原始链表中 没有重复出现 的数字. 思路和上一题类似(参考 力扣(LeetCode)删除排序链表中的重复元素 个人题解)) 只不过这里需要用到一个前 ...
- [LeetCode] 83. Remove Duplicates from Sorted List ☆(从有序链表中删除重复项)
描述 Given a sorted linked list, delete all duplicates such that each element appear only once. Exampl ...
- 【力扣】82. 删除排序链表中的重复元素 II
存在一个按升序排列的链表,给你这个链表的头节点 head ,请你删除链表中所有存在数字重复情况的节点,只保留原始链表中 没有重复出现 的数字. 返回同样按升序排列的结果链表. 示例 1: 输入:hea ...
- 083 Remove Duplicates from Sorted List 有序链表中删除重复的结点
给定一个排序链表,删除所有重复的元素使得每个元素只留下一个.案例:给定 1->1->2,返回 1->2给定 1->1->2->3->3,返回 1->2- ...
随机推荐
- (九)HttpClient获取cookies
原文链接:https://blog.csdn.net/cheny1p1ng/article/details/90780024 旧版本DefaultHttpClient 使用getCookieStore ...
- python生成批量格式化字符串
在学习tensorflow管道化有关操作时,有一个操作是先生成一个文件名队列.在书上使用了这样的代码: filenames = ['test%d.txt'%i for in in range(1,4) ...
- Latex 安装 教程
需要安装texlive和编辑器texstudio. 安装教程如https://www.cnblogs.com/dingruihfut/p/9690073.html
- Mysq数据库索引(B-Tree索引)
一.B-Tree索引的底层结构 所有的值都是按顺序存储的,并且每一个叶子页到根的距离相同,如图所示,B-Tree索引的底层数据结构一般是B+树,反应了MyISAM索引是如何工作的. 二.B-T ...
- 【hdoj】哈希表题hdoj1425
hdoj1425 github链接 #include<cstdio> #include<cstring> using namespace std; const int offs ...
- Python实现监测抖音在线时间,实时记录一个人全天的在线情况
前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:小dull鸟 今天给大家分享一篇有趣的文章,灵感来自于前几天与室友的 ...
- shell 脚本操作informix数据库
shell 脚本操作informix数据库的简单模板: functionName(){ dbaccess << ! database 库名; sql语句; ! } 栗子1:更新数据 fun ...
- Maven中央仓库正式成为Oracle官方JDBC驱动程序组件分发中心
1. 前言 相信参与使用Oracle数据库进行项目开发.运维的同学常常被Oracle JDBC驱动的Maven依赖折磨.现在这一情况在今年二月份得到了改变,甲骨文这个老顽固终于开窍了. 一位甲骨文的工 ...
- 比Minikube更快,使用Kind快速创建K8S学习环境
简述 K8S 如火如荼的发展着,越来越多人想学习和了解 K8S,但是由于 K8S 的入门曲线较高很多人望而却步. 然而随着 K8S 生态的蓬勃发展,社区也呈现了越来越多的部署方案,光针对生产可用的环境 ...
- 关于数据文件的文件头2-P2
文章目录 1 疑问点 2 实验验证 2.1 实验环境 2.2 创建统一区大小管理表空间 2.2.1 统一区大小40k 2.2.2 统一区大小56k 2.2.3 统一区大小64k 2.2.4 统一区大小 ...