LeetCode刷题 --- 链表

news2024/11/24 13:36:47

定义一个node节点

class ListNode {
    int val;

    ListNode next;

    ListNode() {
    }

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

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

206 反转链表

题目:给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

解题:

1、如果head为空或者只有一个节点,那么直接返回结果即可

2、否则,定义一个新链表,遍历旧链表,将每个节点插入到新链表的头部即可。

    public ListNode reverseList(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }

        ListNode res = new ListNode(head.val);

        while (head.next != null) {
            ListNode next = head.next;
            head = next;

            res = new ListNode(next.val, res);

        }
        return res;
    }

203 根据值来删除节点

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。

 

 

定义一个头节点,和两个指针, p和q,如图,循环该链表:

1、如果q指针的值不等于目标值,则分别向后移动一位

2、如果q指针的值等于目标值,则p不懂,q后移,但是p仍指向q

    public List1Node removeElements(List1Node head, int val) {
        // 定义哨兵和双指针
        List1Node myHead = new List1Node(-1, head);
        List1Node p = myHead;
        List1Node q = p.next;
        while (q!=null) {
            if (q.val == val) {
                // 右指针等于目标值,q右移,p不变,但是p还指向q
                q = q.next;
                p.next = q;
            } else {
                // 两个指针均向后移动一位
                p = p.next;
                q = q.next;
            }
        }
        return myHead.next;
    }

19 删除链表的倒数第N个节点

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

 解题1:

1、先获取链表的长度

2、找到倒数第N个节点的前一个节点,指向下一个节点即可

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        int length = length(head);

        ListNode dummy = new ListNode(0,head);
        ListNode cur = dummy;
        for (int i = 1; i < length -n +1; i++) {
            cur = cur.next;
        }
        cur.next = cur.next ==null ? null : cur.next.next;
        return dummy.next;
    }
    
    public int length(ListNode head) {
        if (head == null) {
            return 0;
        }
        ListNode p = head;
        int count = 1;
        while (p.next != null) {
            p = p.next;
            count++;
        }
        return count;
    }
}

解题2

定义两个指针节点p和q,分别指向头节点,先让q节点向后移动n步,然后,在让p和q同时后移,当q指向空的时候,p恰好是倒数第n个节点的前一个节点。

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummy = new ListNode(0, head);
        ListNode p1 = dummy;
        ListNode p2 = dummy;

        for (int i = 0; i < n + 1; i++) {
            p2 = p2.next;
        }

        while (p2 != null) {
            p1 = p1.next;
            p2 = p2.next;
        }

        p1.next = p1.next.next;
        return dummy.next;
    }
}

83、 有序链表去重 (留下一个)

给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 

解题1:

去重,可以使用Map或者set ,遍历链表,如果节点的值已经在集合中存在,那么这个节点就是重复节点,可以删除,如果不存在,则将值存入集合,继续遍历。

class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        if (head==null){
            return head;
        }
        Set<Integer> set = new HashSet<>();
        ListNode node = head;
        set.add(node.val);
        while (node.next!=null) {
            ListNode next = node.next;
            if (set.contains(next.val)){
                node.next = next.next;
            }else {
                node = next;
                set.add(next.val);
            }
        }
        return head;
    }
}

 解题2:

定义哨兵节点,和两个指针节点p/q,比较p/q的值是否相等,如果相等,q后移,p还是指向q,如果不相等,同时后移。

    public ListNode deleteDuplicates(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode dummy = new ListNode(-101, head);
        ListNode p = dummy;
        ListNode q = dummy.next;

        while (q != null) {
            if (q.val == p.val) {
                q = q.next;
                p.next = q;
            } else {
                q = q.next;
                p = p.next;
            }
        }
        return dummy.next;
    }

82. 删除排序链表中的重复元素 (重复的一个不留)

给定一个已排序的链表的头 head , 删除原始链表中所有重复数字的节点,只留下不同的数字 。返回 已排序的链表 。

 解题:

参考上一题,定义哨兵节点,以及三个指针节点,仍然按照p和q比较,遍历,多定义的r节点,是p节点的上一个节点,pq相同的时候,q不断后移,一直移到为null或者值不同,然后将r的下一个节点指向q

    public ListNode deleteDuplicates(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        ListNode dummy = new ListNode(-200, head);
        ListNode r = dummy;
        ListNode p;
        ListNode q;

        while ((p = r.next) != null && (q = p.next) != null) {
            if (p.val == q.val) {
                while (q != null && q.val == p.val) {
                    q = q.next;
                }
                r.next=q;
            } else {
                r = r.next;
            }
        }
        return dummy.next;
    }

21 合并有序链表

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

解题:

定义一个新的头节点,遍历两个链表,哪个值小,就放在新建的头节点后面。如果有一个链表为null,那就把另外一个链表的值全放在新建链表的后面。

    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {

        // 头节点,及指针节点
        ListNode head = new ListNode();
        ListNode node = head;

        while (list1 != null && list2 != null) {
            if (list1.val <= list2.val) {
                node.next = list1;
                list1 = list1.next;
            } else {
                node.next = list2;
                list2 = list2.next;
            }
            node = node.next;
        }
        if (list1 != null) {
            node.next = list1;
        }
        if (list2 != null) {
            node.next = list2;
        }
        return head.next;
    }

23、和并多个升序链表

题解:参考21题,遍历链表,两两合并

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        ListNode node = null;
        for (int i = 0; i < lists.length; i++) {
            node = mergeTwoLists(lists[i], node);
        }
        return node;
    }
    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {

        // 头节点,及指针节点
        ListNode head = new ListNode();
        ListNode node = head;

        while (list1 != null && list2 != null) {
            if (list1.val <= list2.val) {
                node.next = list1;
                list1 = list1.next;
            } else {
                node.next = list2;
                list2 = list2.next;
            }
            node = node.next;
        }
        if (list1 != null) {
            node.next = list1;
        }
        if (list2 != null) {
            node.next = list2;
        }
        return head.next;
    }
}

876. 链表的中间结点

给你单链表的头结点 head ,请你找出并返回链表的中间结点。

如果有两个中间结点,则返回第二个中间结点。

 

 

题解:

快慢指针法,定义两个指针,初始分别指向头节点,p每次前进一步,q每次前进两步,当q前进时为null了,此时p指向的就是题目要求的中间节点。

    public ListNode middleNode(ListNode head) {
        ListNode p1 = head;
        ListNode p2 = head;

        while (p2 != null && p2.next != null) {
            p1 = p1.next;
            p2 = p2.next.next;
        }
        return p1;
    }

243 回文链表

判断一个链表是不是回文链表,就是正读反读是一样的。

题解:

将给定的链表反转,然后将新链表和老链表逐个比较,一致则为true,否则为false。

    public boolean isPalindrome(ListNode head) {
        ListNode reverse = reverse(head);
        while (head != null) {
            if (head.val != reverse.val) {
                return false;
            }
            head = head.next;
            reverse = reverse.next;
        }
        return true;
    }

    public ListNode reverse(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }

        ListNode res = new ListNode(head.val);

        while (head.next != null) {
            ListNode next = head.next;
            head = next;
            res = new ListNode(next.val, res);

        }
        return res;
    }

链表判环算法:

用快慢指针的方法(龟兔赛跑算法):

  1. 阶段1
    1. 龟一次走一步,兔子一次走两步
    2. 兔子能走到终点,那么就不存在环
    3. 兔子能追上龟(再次相遇),说明存在环。
  2. 阶段2
    1. 再次相遇时,兔子留在原地不动,龟退回到起点
    2. 兔子和龟都每次走一步
    3. 再次相遇的时候,相遇点就是环的入口。

解释一下阶段2:

  • 假设起点到环入口是a步,环一圈是b步
  • 从起点开始,走a+b*n都可以到环的入口
  • 第一次相遇:
    • 兔走了a + m*b +k 步,k是距离环入口的距离
    • 龟走了a + n*b +k 步,k是距离环入口的距离, m>n
    • 兔子走的路程是龟的两倍,所以 龟 = 兔 - 龟 = x*n 圈,龟走的是圈的整数倍
  • 因为走a+b*n都可以到环的入口,因此,从相遇点开始,在走a步,就可以找到环的入口。
  • 这个还有一个小bug,就是如果a=0,那么起点就是环入口。

141、判断是否是环形链表

根据上述判环算法,可以直接写出代码

    public boolean hasCycle(ListNode head) {
        ListNode p = head;
        ListNode q = head;

        while (q != null && q.next != null) {
            p = p.next;
            q = q.next.next;
            if (q == p) {
                return true;
            }
        }
        return false;
    }

142 找到环形链表的入口

根据上述算法,可以直接在141的基础上改写代码

    public ListNode detectCycle(ListNode head) {
        ListNode p = head;
        ListNode q = head;

        while (q != null && q.next != null) {
            p = p.next;
            q = q.next.next;
            if (q == p) {
                // 判断里面改写代码,将p重新指向头节点,然后两个节点每次分别走一步
                p = head;
                while (true) {
                    // 进到循环之后,先判断两个节点是否相等,
                    // 解决了头结点就是入口节点的问题。
                    if (q == p) {
                        return q;
                    }
                    p = p.next;
                    q = q.next;
                }
            }
        }
        return null;
    }

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

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

相关文章

【FAQ】视频编辑服务常见问题及解答

Q1问题描述 1、 访问贴纸等素材的时候提示“网络异常&#xff0c;请重试”怎么办&#xff1f; 2、 使用AI能力时&#xff0c;提示“errorCode:20124 errorMsg:Method not Allowed”&#xff1f; 解决方案 请做以下检查&#xff1a; 1、 在代码中检查鉴权信息是否已设置。如…

AI法律助手:ChatGPT如何提供智能化解决方案

日常生活中&#xff0c;民事纠纷不可避免&#xff0c;涉及到多种问题&#xff0c;如合同纠纷、劳动纠纷、婚姻家事、民间借贷、交通事故、工伤赔偿、房屋租赁等。解决这些问题&#xff0c;需要花费大量时间和精力&#xff0c;但现在&#xff0c;我们有了一种全新的解决方案&…

蓝库云:建立智慧零售,零代码技术能起到什么作用

随着科技的进步更多智能化的技术及应用融入我们生活中&#xff0c;例如零售行业在现代零售和传统零售的区别不仅在于营销策略、销售方式、销售渠道以及运营模式等方面&#xff0c;更多是在现代零售则更注重数字化营销&#xff0c;发挥社交媒体和电子商务渠道的作用&#xff0c;…

“前端”工匠系列(二):合格的工匠,怎么做好价值落地 | 京东云技术团队

一、“技术鄙视链&#xff1f;” 如果你是一个技术人&#xff0c;相信都知道技术圈有个相互的鄙视链&#xff0c;这个链条从技术人自己认知的角度在以业务价值为中心嵌套的一层一层的环&#xff0c;就像洋葱&#xff0c;具体的描述这里不赘述了。 出门左拐随便抓住一个人问一…

RabbitMQ应用问题——消息补偿机制以及代码示例

RabbitMQ应用问题——消息补偿机制以及代码示例 RabbitMQ应用问题 消息可靠性的保障 消息补偿机制 详细说明 这里使用了简单的代码进行演示&#xff0c;订单的消费者没有写&#xff0c;在订单的消费同时&#xff0c;发送一条增加积分消息到积分队列。 详细流程途中都有注明…

STM32+ov7725+ESP8266实现无线图传-完成上位机图像显示

一、需求 stm32f407探索者开发板和STM32F103ZET6战舰开发板。接正点原子ov5640、OV7725、OV2640摄像头,通过esp8266Wi-Fi模块(透传模式)将摄像头采集到的rgb565格式图片通过tcp/ip协议上传到上位机显示。 二、设计思路 【1】使用QT开发上位机,建立TCP服务器,接收ESP8266…

DistilPose: Tokenized Pose Regression with Heatmap Distillation

论文名字&#xff1a;DistilPose&#xff1a;使用热图蒸馏的令牌化姿势回归 论文地址&#xff1a;2303.02455.pdf (arxiv.org)https://arxiv.org/pdf/2303.02455.pdf项目地址&#xff1a;yshMars/DistilPose: Implementation for: DistilPose: Tokenized Pose Regression with…

科幻风的卡片视频播放

上一篇博文展示了卡片中的VR展示&#xff0c;那篇主要是卡片的3D转动来展示未显示的部分图片。这篇&#xff0c;我们来点科幻的。 我们在卡片中播放视频的同时来拖动卡片或转动它。像下面那样&#xff1a; 这个主要依赖了两个库&#xff0c;具体代码如下&#xff1a; <!D…

智能问答支持自定义问答

# -*- coding: utf-8 -*- # Time : 2023-5-12 14:15 # Author : shenzh # FileName: chat_bot_v1.py # Software: PyCharm """Description:一期智能机器人设计完成&#xff0c;支持自定义问题和答案随时增加功能""" import json import jie…

NOV Diagram for .NET Crack

NOV Diagram for .NET Crack 增加了对Microsoft.NET 7.0的支持-NOV现在完全支持.NET Core 7.0&#xff0c;此外还支持Microsoft.NET Framework 4.7.2、.NET Core 5.0和.NET Core 6.0的内部版本。 添加了对读取Microsoft Visio 2003-2010绘图(VSD文件)的支持。 改进了SVG导出。 …

哈希表应用——位图

应用场景&#xff1a;海量数据处理&#xff08;这里的海量是指一般数据量非常大如以亿为单位的数据量&#xff09; 目录 面试题 位图概念 位图的实现 位图的应用 应用一 应用二 位图应用变形 面试题 给40亿个不重复的无符号整数&#xff0c;没排过序。给一个无符号整数&…

Java之多线程进阶

目录 一.上节内容复习 1.线程池的实现 2.自定义一个线程池,构造方法的参数及含义 3.线程池的工作原理 4.拒绝策略 5.为什么不推荐系统提供的线程池 二.常见的锁策略 1.乐观锁和悲观锁 2.轻量级锁和重量级锁 3.读写锁和普通互斥锁 4.自旋锁和挂起等待锁 5.可重入锁和…

精彩回顾 | Fortinet Accelerate 2023·中国区巡展厦门站

Fortinet Accelerate 2023中国区 5月16日&#xff0c;Fortinet Accelerate 2023中国区巡展来到魅力“鹭岛”——厦门&#xff0c;技术、产品和业务专家&#xff0c;携手亚马逊云科技、唯一网络等云、网、安合作伙伴&#xff0c;与交通、物流、金融等各行业典型代表客户&#x…

GPT大语言模型Vicuna本地化部署实践(效果秒杀Alpaca) | 京东云技术团队

​ 背景 上一篇文章《[GPT大语言模型Alpaca-lora本地化部署实践]》介绍了斯坦福大学的Alpaca-lora模型的本地化部署&#xff0c;并验证了实际的推理效果。 总体感觉其实并不是特别理想&#xff0c;原始Alpaca-lora模型对中文支持并不好&#xff0c;用52k的中文指令集对模型进…

信息安全工程实验——口令攻击和钓鱼攻击(自用)

目录 实验目的 实验原理 实验内容 练习1windows口令破解 1、基本操作 2、思考与总结 练习2&#xff1a;QQ 邮箱的钓鱼攻击 1、构造钓鱼页面 2、接收钓鱼所得的账号和密码&#xff08;分档&#xff09; 3、实验验证 4、思考与总结 实验目的 &#xff08;1&#xff09…

网络安全实验——信息收集与主机发现

目录 实验目的 实验原理 实验内容 1.信息搜集 1.ping探测 2. Nmap扫描 3. 探测总结 2.主机发现程序开发 3.主机发现 实验总结 实验目的 1.了解信息搜集的一般步骤。 2.学会熟练使用ping命令。 3.学会利用Nmap等工具进行信息搜集。 4.了解IP助手函数。 5.掌握Sen…

Python学习29:存款买房(B)

描述‪‬‪‬‪‬‪‬‪‬‮‬‪‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‪‬‭‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‮‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‭‬‫‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‪‬ 你刚刚大学毕业&#xff0c;…

李莫愁给张无忌朋友圈点赞?详解SpringBoot事件机制

Spring Boot的事件机制是基于Spring框架的事件机制实现的。Spring Boot中的事件机制可以让我们在应用程序中监听和响应特定的事件&#xff0c;例如应用程序启动、关闭、上下文刷新等。 接下来&#xff0c;我们通过一个案例&#xff0c;来讲解具体怎么使用。 这个案例就是李莫…

一文看懂增值税发票识别OCR:从技术原理到 API Java 示例代码接入

引言 增值税发票识别OCR API是一项重要的技术创新&#xff0c;它在如今信息化的商业环境中发挥着重要作用。通过利用该API&#xff0c;企业和机构能够实现增值税发票的自动化识别和信息提取&#xff0c;从而在财务管理、票据核对、报销流程等方面带来许多好处。 本文将详细介…

Istio virtual service 超时和重试

在使用xshell去远程连接服务器的时候没有反应&#xff0c;这样可能等了几分钟&#xff0c;这样按下crtlc终止就行了。 有些时候微服务是多个服务组成的&#xff0c;a服务会去调用b服务&#xff0c;可能因为网络问题或者连接问题&#xff0c;没有连接成功&#xff0c;那么会尝试…