目录
最近玩OJ赛,发现对算法的理解还需要更加扎实,code能力还可以进一步提升,所以做这样一个算法的系列文章,用于记录学习心得,交流经验,更好地进步和成长。
给定一个已排序的链表的头 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)
链接:力扣