• 力扣 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++

    1. /**
    2. * Definition for singly-linked list.
    3. * struct ListNode {
    4. * int val;
    5. * ListNode *next;
    6. * ListNode() : val(0), next(nullptr) {}
    7. * ListNode(int x) : val(x), next(nullptr) {}
    8. * ListNode(int x, ListNode *next) : val(x), next(next) {}
    9. * };
    10. */
    11. class Solution {
    12. public:
    13. ListNode* deleteDuplicates(ListNode* head) {
    14. ListNode* newHead = head; //head一会儿要用于向后遍历链表,所以会发生变化,这里创建一个新的头结点用于保存初始头结点以便返回
    15. while(head and head->next){ //只有当头结点和其下一位的结点都有值时才有比较的意义,同时可以防止越界
    16. if(head->val == head->next->val){ //这里就是比较两个元素的值了,head->val 和 head->next->val 是C++ 中链表元素值的表示方法
    17. head->next = head->next->next; //如果两元素相同,头结点不变,将指针指向下一元素的下一个,继续比较
    18. }else{ //如: 1->1->1->1->2
    19. //若不相等,更新头结点,进入下一轮比较 //索引 0, 1, 2, 3, 4
    20. head = head->next; //第一次比较后 1->1->1->2
    21. } //索引 0,2,3,4 在链表中的指针会直接跨越要删除的结点,指向该结点的下一位,实际操作中会更新索引,此处还引用原链表索引便于理解
    22. //第二次比较 1->1->2
    23. //索引 0,3,4
    24. //最后一次比较 1->2
    25. //索引 0,4
    26. }
    27. return newHead;
    28. }
    29. };

    彩蛋 使用集合的方式来实现

    时间复杂度O(N),空间复杂度O(N)

    1. /**
    2. * Definition for singly-linked list.
    3. * struct ListNode {
    4. * int val;
    5. * ListNode *next;
    6. * ListNode() : val(0), next(nullptr) {}
    7. * ListNode(int x) : val(x), next(nullptr) {}
    8. * ListNode(int x, ListNode *next) : val(x), next(next) {}
    9. * };
    10. */
    11. class Solution {
    12. public:
    13. ListNode* deleteDuplicates(ListNode* head) {
    14. //采用集合的方法实现
    15. set<int> visited;
    16. ListNode* node = head;
    17. ListNode* flag = new ListNode(0,head);
    18. while(node){
    19. if(visited.count(node->val)){
    20. flag->next = node->next;
    21. }else{
    22. visited.insert(node->val);
    23. flag = flag->next;
    24. }
    25. node = node->next;
    26. }
    27. return head;
    28. }
    29. };


    总结

    以上就是今天要讲的内容,本文仅仅简单讲解了《83. 删除排序链表中的重复元素》这一题目,算法需要细致入微的思考。

    题目来源

    来源:力扣(LeetCode)
    链接:力扣

  • 相关阅读:
    计算机视觉(CV)技术的优势和挑战
    GBase 8s资源管理
    一文了解有限空间作业管理办法
    如果想搭建在线客服,应该如何建、
    SpringCloud 05 Eureka集群环境配置和CAP
    【计算机视觉 | 目标检测】arxiv 计算机视觉关于目标检测的学术速递(8 月 25 日论文合集)
    Mysql锁相关知识补充
    常用的一些高阶函数
    .NET 8 Preview 5发布,了解一下Webcil 是啥
    功率放大器在无线收发系统中的作用
  • 原文地址:https://blog.csdn.net/m0_51787573/article/details/127688647