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

news2025/3/1 16:10:46

删除链表重复元素

题目描述

思路分析 

思路1:采用一次遍历,内部循环判定是否相等

具体分析一下指针移动

 外部循环判定卡住的位置

c语言代码:

#include <stdio.h>
#include <stdlib.h>

struct ListNode
{
    int val;
    struct ListNode *next;
};

struct ListNode *deleteDuplicates(struct ListNode *head)
{
    // 把头结点做个备份的思想很好
    if (!head)
    {
        return head;
    }

    // 新建一个节点备份头结点,这也是一个哑结点
    struct ListNode *dummy = (struct ListNode *)malloc(sizeof(struct ListNode));
    dummy->next = head; // 下一个节点保存头结点,我们要让指针指向两比较结点最前面的一个结点

    struct ListNode *cur = dummy; // 让cur结点指向哑结点,cur结点改动,哑结点自然也会改动,最后要返回哑结点的next,也就是从头开始

    // 开始外部整体循环一次
    // 内部相同数据多次循环
    while (cur->next != NULL && cur->next->next != NULL)
    {
        // 如果遇到相同的节点,让内部指针移动
        // 1  1  1 2  2 3
        if (cur->next->val == cur->next->next->val)
        {
            int x = cur->next->val;
            // 开始内部循环相同结点
            while (cur->next != NULL && cur->next->val == x)
            {
                cur->next = cur->next->next; // 1 1(指向这第一次) 1 2 2 3 //还会循环一次,指向 1 1 1 2(第二次,跳出内部) 2
            }
        }
        else
        {
            // 如果不相等cur就正常往下面走,但是不改变next指向
            cur = cur->next;
        }
    }

    // 整体循环完之后,返回dummy指向的next头结点
    return dummy->next; // 返回头结点的地址
}

void display(struct ListNode *head)
{
    while (head != NULL) 
    {
        printf("%d ", head->val);
        head = head->next;
    }
    printf("\n---------\n");
}

int main()
{

    struct ListNode *head = (struct ListNode *)malloc(sizeof(struct ListNode));
    head->val = 1;
    struct ListNode *p1 = (struct ListNode *)malloc(sizeof(struct ListNode));
    p1->val = 1;
    struct ListNode *p2 = (struct ListNode *)malloc(sizeof(struct ListNode));
    p2->val = 2;
    struct ListNode *p3 = (struct ListNode *)malloc(sizeof(struct ListNode));
    p3->val = 2;
    struct ListNode *p4 = (struct ListNode *)malloc(sizeof(struct ListNode));
    p4->val = 3;
    struct ListNode *p5 = (struct ListNode *)malloc(sizeof(struct ListNode));
    p5->val = 4;
    struct ListNode *p6 = (struct ListNode*)malloc(sizeof(struct ListNode));
    p6->val = 4;
    
    //把结点都连接起来
    head->next = p1;
    p1->next = p2;
    p2->next = p3;
    p3->next = p4;
    p4->next = p5;
    p5->next = p6;
    p6->next = NULL;

    //打印节点
    display(head);

    //删除重复结点
    //头结点其实就是dummy结点的next结点
    head = deleteDuplicates(head);

    display(head);

    return 0;
}

java代码实现:

package com.pxx.leetcode.delDuplicates82;

//数据节点
//直接用一个对象来做
class ListNode {
    int val;
    ListNode next;

    public ListNode(int val, ListNode next) {
        this.val = val;
        this.next = next;
    }

    public ListNode() {
    }

    public ListNode(int val) {
        this.val = val;
    }
}

class Solution {
    public ListNode deleteDuplicates(ListNode head) {
         if (head == null) {
             return head;
         }

         //哑结点
        ListNode dummy = new ListNode(0, head);//哑结点的next指向头结点

        //移动结点
        ListNode cur = dummy;//指针直接指向了哑结点

        //开始整体一次循环移动
        while (cur.next != null && cur.next.next != null) {
            //next与next.next是否相等
            if (cur.next.val == cur.next.next.val) {
                //备份一个相等的节点值用于里布进行循环判定
                int x = cur.next.val;
                // (指针可以理解为先在头部) 1 1 1
                while (cur.next != null && cur.next.val == x) {
                    //更改这片空间指向的next
                    //如果头结点不一样,头结点也会改动
                    cur.next = cur.next.next;//第一次 1 1(指向这个位置) 1
                }
            } else {
                cur = cur.next;
            }
        }
        return dummy.next;
    }
}



public class Solution1 {

}

思路2:采用递归的方式来做

上面就是如果头结点与它的next结点的值一样,那么就把这个头结点的next交给move结点,然后内部循环是否继续相等,知道不相等的时候跳出循环,继续以move为头结点进行递归,一旦到了一个与next不相等的位置,那么就把这个当前move指针的next继续下面递归,直到最后next等于NULL时候,停止递归,开始返回数据。

那么最早的头一定是最晚返回的数据,所以最后的head,一定就是头结点了。

c语言代码实现:

#include <stdio.h>
#include <stdlib.h>


struct ListNode 
{
    int val;
    struct ListNode *next;
};

//目的:返回第一个不是重复数字的头
//过程:递归控制有效指针的next移动
struct ListNode* deleteDuplicates(struct ListNode* head) 
{
    //已经是最后一个结点
    if (head == NULL || head->next == NULL)
    {
        return head;
    }

    if (head->val != head->next->val)
    {
        //不相等直接改变next指向
        head->next = deleteDuplicates(head->next);
    }
    else 
    {
        struct ListNode *move = head->next;
        //把第一个有相同值节点的头当成头结点传入
        while (move != NULL && move->val == head->val) 
        {
            //最后move移动到没有相同结点的位置
            move = move->next;
        }   

        return deleteDuplicates(move);//把不是相同的节点传进来
    }

    //返回实际的next地址
    //最后程序结束
    return head;
}

void display(struct ListNode *head)
{
    printf("\n-----\n");
    while (head != NULL) 
    {
        printf("%d  %d\n", head->val, head->next);
        head = head->next;
    }
    printf("\n---------\n");
}


int main()
{
    struct ListNode *head = (struct ListNode *)malloc(sizeof(struct ListNode));
    head->val = 1;
    struct ListNode *p1 = (struct ListNode *)malloc(sizeof(struct ListNode));
    p1->val = 3;
    struct ListNode *p2 = (struct ListNode *)malloc(sizeof(struct ListNode));
    p2->val = 3;
    struct ListNode *p3 = (struct ListNode *)malloc(sizeof(struct ListNode));
    p3->val = 5;
    /*
    struct ListNode *p4 = (struct ListNode *)malloc(sizeof(struct ListNode));
    p4->val = 4;
    struct ListNode *p5 = (struct ListNode *)malloc(sizeof(struct ListNode));
    p5->val = 4;
    struct ListNode *p6 = (struct ListNode*)malloc(sizeof(struct ListNode));
    p6->val = 5;
    */

    //把结点都连接起来
    head->next = p1;
    p1->next = p2;
    p2->next = p3;
    p3->next = NULL;

    display(head);

    head = deleteDuplicates(head);

    display(head);


    return 0;
}

java代码实现

package com.pxx.leetcode.delDuplicates82;

//数据节点
//直接用一个对象来做
class ListNode {
    int val;
    ListNode next;

    public ListNode(int val, ListNode next) {
        this.val = val;
        this.next = next;
    }

    public ListNode() {
    }

    public ListNode(int val) {
        this.val = val;
    }
}

//采用一次遍历的方式来做
class Solution {
    public ListNode deleteDuplicates(ListNode head) {
         if (head == null) {
             return head;
         }

         //哑结点
        ListNode dummy = new ListNode(0, head);//哑结点的next指向头结点

        //移动结点
        ListNode cur = dummy;//指针直接指向了哑结点

        //开始整体一次循环移动
        while (cur.next != null && cur.next.next != null) {
            //next与next.next是否相等
            if (cur.next.val == cur.next.next.val) {
                //备份一个相等的节点值用于里布进行循环判定
                int x = cur.next.val;
                // (指针可以理解为先在头部) 1 1 1
                while (cur.next != null && cur.next.val == x) {
                    //更改这片空间指向的next
                    //如果头结点不一样,头结点也会改动
                    cur.next = cur.next.next;//第一次 1 1(指向这个位置) 1
                }
            } else {
                cur = cur.next;
            }
        }
        return dummy.next;
    }
}


//采用递归来做
class Solution1 {
    public ListNode deleteDuplicates(ListNode head) {
        //最后一个结点就直接null,不做了
        if (head == null || head.next == null) {
            return head;
        }

        if (head.val != head.next.val) {
            //指针直接next往下面走动
            head.next = deleteDuplicates(head.next);
        } else {
            ListNode move = head.next;
            //移动到非相同数值的位置
            while (move != null && move.val == head.val) {
                move = move.next;
            }
            return deleteDuplicates(move);//继续传入下一个值递归
        }
        return head;
    }
}

public class Lc1 {
    public static void main(String[] args) {
        ListNode head = new ListNode(1,null);
        ListNode node1 = new ListNode(3,null);
        ListNode node2 = new ListNode(3,null);
        ListNode node3 = new ListNode(5,null);

        head.next = node1;
        node1.next = node2;
        node2.next = node3;
        node3.next = null;

        //打印原始链表
        display(head);

        //删除重复元素,调用递归的方法
        Solution1 s1 = new Solution1();
        head = s1.deleteDuplicates(head);
        display(head);
    }

    public static void display(ListNode head) {
        while (head != null) {
            System.out.print(head.val + " ");
            head = head.next;
        }
        System.out.println();
        System.out.println("-----");
    }

}

好了,祝大家早安午安晚安

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1157982.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Paper reading: segment anything in high quality NIPS2023

最近发展起来的SAM模型&#xff0c;表示分割模型的一个大的跃进&#xff0c;尤其是在零样本的能力和灵活提升方面。尽管利用1.1bollion的mask&#xff0c;SAM在掩码预测方面已经存在很大的问题&#xff0c;尤其是目标有着复杂结构的时候。 我们提出一个HA-SAM。 设计学习一个…

2023腾讯云双11优惠价格表发布:轻量云服务器和CVM云服务器的优惠价格

双十一购物狂欢节即将来临&#xff0c;作为IT行业的从业者或企业用户&#xff0c;我们也可以享受到腾讯云在这个节日里带来的超值优惠。近日&#xff0c;腾讯云发布了2023年双十一优惠价格表&#xff0c;其中包括了轻量云服务器和CVM云服务器的各项优惠价格。本文将为您详细介绍…

labelme安装后无法启动

问题 labelme安装后无法启动&#xff0c;输入labelme后出现了如下错误信息&#xff1a; labelme : 无法将“labelme”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写&#xff0c;如果包括路径&#xff0c;请确保路径正确&#xff0c;然后再试一次。 所…

2023年10月文章一览

2023年10月编程人总共更新了6篇文章&#xff1a; 1.2023年9月文章一览 2.Programming abstractions in C阅读笔记&#xff1a;p161-p165 3.Programming abstractions in C阅读笔记&#xff1a;p166-p175 4.Programming abstractions in C阅读笔记&#xff1a;p176-p178 5.…

冒泡与捕获事件

一.冒泡与捕获 1.概念。 冒泡事件&#xff1a;微软公司提出的&#xff0c;事件由子元素传递到父元素的过程叫做冒泡&#xff08;false&#xff09;。 捕获事件&#xff1a;网景公司提出的&#xff0c;事件由父元素传递到子元素的过程叫做事件捕获&#xff08;ture&#xff09…

晃电的原因以及如何治理?

安科瑞 须静燕 晃电的定义 国标GB/T 30137-2013 中定义:工频电压方均根值突然降至额定值的90%~10%&#xff0c;持续时间为10ms~ 1min后恢复正常的现象 晃电的原因 短路故障 绝缘闪络 大功率电机启动 雷击浪涌 进线失电时备自投或快切 晃电的危害 对公共用户影响较小 …

如何看待阿里云99元服务器新老用户同享?

如何看待阿里云99元服务器老用户可买&#xff1f;阿里云急了&#xff0c;阿里云老用户与狗的营销策略要被打破了吗&#xff1f;并且续费不涨价&#xff0c;依旧是99元&#xff0c;阿里云急了&#xff1f; 2023阿里云服务器优惠活动来了&#xff0c;以前一直是腾讯云比阿里云优…

2023年十大地推网推拉新接单平台,都是一手单和官方渠道

2023年做拉新推广的地推人员&#xff0c;一定不要错过这十个接单平台&#xff0c;助你轻松找到一手单&#xff0c;这10个平台分别是&#xff1a; &#xff08;主推&#xff1a;聚量推客&#xff09; 我们也拿到了一手邀请码&#xff1a;000000 1&#xff1a;聚量推客 “聚量推…

jsoncpp fatal error C1083: 无法打开编译器生成的文件

使用jsoncpp库的时候&#xff0c;在Debug模式下正常&#xff0c;但是release却报错&#xff0c;开始以为是开发项目设置问题&#xff0c;于是网络搜索&#xff0c;发现是jsoncpp的编译选项问题。 修改生成静态库文件的工程的属性&#xff1a;路径为&#xff1a;菜单&#xff0…

霍尔效应测试系统

霍尔效应是电磁效应的一种&#xff0c;这一现象是美国物理学家霍尔&#xff08;E.H.Hall&#xff0c;1855—1938&#xff09;于1879年在研究金属的导电机制时发现的。当电流垂直于外磁场通过半导体时&#xff0c;载流子发生偏转&#xff0c;垂直于电流和磁场的方向会产生一附加…

pytorch复现_IOU

定义了一个compute_iou函数&#xff0c;用于计算两个矩形框&#xff08;boxA和boxB&#xff09;之间的交并比&#xff08;IOU&#xff0c;Intersection over Union&#xff09;。IOU是一种常用的度量&#xff0c;用于评估两个矩形框的重叠程度。 在代码中&#xff0c;函数的输入…

网络安全漏洞管理与修复: 深入研究漏洞管理流程,包括漏洞扫描、评估、修复和验证。

网络安全是当今数字时代的重要议题&#xff0c;随着技术的不断发展&#xff0c;网络攻击和漏洞问题也日益复杂。在这篇文章中&#xff0c;我们将深入研究网络安全漏洞管理与修复的流程&#xff0c;包括漏洞扫描、评估、修复和验证。通过理解和实施这一流程&#xff0c;组织可以…

2023-10-31 LeetCode每日一题(每棵子树内缺失的最小基因值)

2023-10-31每日一题 一、题目编号 2003. 每棵子树内缺失的最小基因值二、题目链接 点击跳转到题目位置 三、题目描述 有一棵根节点为 0 的 家族树 &#xff0c;总共包含 n 个节点&#xff0c;节点编号为 0 到 n - 1 。给你一个下标从 0 开始的整数数组 parents &#xff0…

Vue:实现输入vue组件名称,就可以从网页上加载出组件

作者:CSDN @ _乐多_ 本文记录了使用动态组件实现在网页上输入vue组件名称,就可以从网页上直接加载组件的功能的代码。 实现效果如下所示, 在许多Vue.js应用中,我们有大量的组件,但并不是每个组件都需要在应用初始化时加载。动态加载组件的好处包括: 减小初始加载时间:…

[已解决]Mysql想删掉一个表里所有的数据,直接删总是卡住

问题 产生"假锁" Mysql想删掉一个表里所有的数据&#xff0c;直接删总是卡住 思路 产生"假锁"原因 MySQL如果频繁的修改一个表的数据&#xff0c;那么这么表会被锁死。造成假死现象。在网上试过很多种解决方法,重启mysql服务,重连数据库都没有用。 温馨…

谷歌野心真不小!斥巨资扩张在人工智能界的战略地位,Anthropic公司成为跳板

原创 | 文 BFT机器人 近日&#xff0c;谷歌宣布对Anthropic进行重大投资&#xff0c;此举突显了谷歌这家科技巨头对人工智能 (AI) 的不断深化的承诺。此次&#xff0c;谷歌20亿美元的注资不仅增强了自身在快速发展的人工智能领域的立足点&#xff0c;而且标志着该行业动态的深…

[nodejs] 爬虫加入并发限制并发实现痞客邦网页截图

今晚想给偶像的相册截个图,避免某一天网站挂了我想看看回忆都不行,用的是js的木偶师来爬虫台湾的部落格,效果图大概是这样,很不错 问题来了.我很贪心, 我想一次性把相册全爬了,也就是并发 ,这个人的相册有19个!!我一下子要开19个谷歌浏览器那个什么进程, 然后程序就崩了, 我就想…

题号1577 E.迷宫plus (有趣的BFS练习)

题目&#xff1a;样例&#xff1a; 输入 1 5 5 LRLRL LLLLL RRRRR UUUUU UUUUD 输出 4 思路&#xff1a; 一般遇到坐标迷宫&#xff0c;基本上都是DFS 或者 BFS &#xff0c;这里多了一个条件就是要最少修改操作数&#xff0c;所以我们DFS很难控制这一条件&#xff0c;通过 BF…

堆排序之“TOP-K”问题

目录 一、什么是TOP-K问题 二、解决思路 一般的正常思路&#xff1a; 最优的解决思路&#xff1a; 三、文件流中实践TOP-K方法 创建包含足够多整数的文件&#xff1a; 找出最大的K个数 完整版代码&#xff1a; 前面我已经学习过使用“堆排序”对数组排降序了&#xf…