目录
第一站 LeetCode 新手村
前言
最近玩OJ赛,发现对算法的理解还需要更加扎实,code能力还可以进一步提升,所以做这样一个算法的系列文章,用于记录学习心得,交流经验,更好地进步和成长。
83. 删除排序链表中的重复元素
题目描述
给定一个已排序的链表的头 head
, 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。
示例1
输入:head = [1,1,2] 输出:[1,2]
示例 2
输入:head = [1,1,2,3,3] 输出:[1,2,3]
提示
- 链表中节点数目在范围
[0, 300]
内 -100 <= Node.val <= 100
- 题目数据保证链表已经按升序 排列
解题思路
预知
LeetCode是核心代码模式,所以只需要考虑核心算法,输入由系统自动完成,最后的输出以return返回;聪明的你不妨先看看题目,了解题意,阅读体验感更佳。
思路
本题要求的是,去除链表中所有重复的元素,每个元素只保留一个,采用操作原链表的方法就可以实现,时间复杂度为O(N)因为要逐个访问链表中的元素,空间复杂度为O(1),并没有适用额外的空间;具体的实现思路请参考代码和注释,代码是台阶,注释是抓手,有台阶,有抓手省时又省力;
思考中的一点收获
这道题思路还是比较简单的,就是需要注意在操作过程中的比较问题
本来想着通过更新头结点的方式来做,比较头结点和它下一个元素的值,如果相同就指向相同元素的下一个,然后将头结点更新为被指向的元素,显然这样的思路是存在很大问题的,比如:
元素:1,1,1,2,3
索引:0,1,2,3,4
此处我们默认索引从0开始
在这样的一个链表中,头结点会先是1,因为,下一个元素和头结点相同,所以头结点的下一个指针会指向索引为2的元素,此时元素变为
元素:1,1,2,3
索引:0,1,2,3
同时更新头结点,显然head位于了索引为1的位置,而该位置的元素会继续和它的下一个元素比较,由于元素2和1不同,继续更新头结点,相信看到这,朋友们已经发现,这样会漏掉索引为0和索引为1位置元素的比较,这样即使有重复的元素,也无法识别出来
代码
C++
/**
* Definition for singly-linked list.
* 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) {}
* };
*/
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
ListNode* newHead = head; //head一会儿要用于向后遍历链表,所以会发生变化,这里创建一个新的头结点用于保存初始头结点以便返回
while(head and head->next){ //只有当头结点和其下一位的结点都有值时才有比较的意义,同时可以防止越界
if(head->val == head->next->val){ //这里就是比较两个元素的值了,head->val 和 head->next->val 是C++ 中链表元素值的表示方法
head->next = head->next->next; //如果两元素相同,头结点不变,将指针指向下一元素的下一个,继续比较
}else{ //如: 1->1->1->1->2
//若不相等,更新头结点,进入下一轮比较 //索引 0, 1, 2, 3, 4
head = head->next; //第一次比较后 1->1->1->2
} //索引 0,2,3,4 在链表中的指针会直接跨越要删除的结点,指向该结点的下一位,实际操作中会更新索引,此处还引用原链表索引便于理解
//第二次比较 1->1->2
//索引 0,3,4
//最后一次比较 1->2
//索引 0,4
}
return newHead;
}
};
彩蛋 使用集合的方式来实现
时间复杂度O(N),空间复杂度O(N)
/**
* Definition for singly-linked list.
* 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) {}
* };
*/
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
//采用集合的方法实现
set<int> visited;
ListNode* node = head;
ListNode* flag = new ListNode(0,head);
while(node){
if(visited.count(node->val)){
flag->next = node->next;
}else{
visited.insert(node->val);
flag = flag->next;
}
node = node->next;
}
return head;
}
};
总结
以上就是今天要讲的内容,本文仅仅简单讲解了《83. 删除排序链表中的重复元素》这一题目,算法需要细致入微的思考。
题目来源
来源:力扣(LeetCode)
链接:力扣