力扣 83. 删除排序链表中的重复元素

目录

第一站 LeetCode 新手村

前言

83. 删除排序链表中的重复元素

题目描述

解题思路

代码

总结

题目来源


第一站 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)
链接:力扣

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值