【链表】算法例题

news2024/11/28 2:28:26

 

目录

 八、 链表

57. 环形链表 ① ×

58. 两数相加 ② √

59. 合并两个有序链表 ① √-

60. 随机链表的复制 ②

61. 反转链表II ② ×

62. K个一组翻转链表 ③

63. 删除链表的倒数第N个结点 ② √-

64. 删除排序链表中的重复元素II ②  √-

65. 旋转链表 ② √-

66. 分隔链表 ② √

67. LRU缓存 ②


八、 链表

57. 环形链表 ① ×

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

如果链表中存在环 ,则返回 true 。 否则,返回 false 。

示例 1:

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

输入:head = [1], pos = -1
输出:false
解释:链表中没有环。

提示:

  • 链表中节点的数目范围是 [0, 104]
  • -105 <= Node.val <= 105
  • pos 为 -1 或者链表中的一个 有效索引 。

进阶:你能用 O(1)(即,常量)内存解决此问题吗?

力扣解析:

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

方法2:(0ms)

    public boolean hasCycle(ListNode head) {
        if (head == null || head.next == null) return false;
        int n = 10010;
        while (n -- > 0) {
            head = head.next;
            if (head == null) return false;
        }
        return true;
    }

58. 两数相加 ② √

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例 1:

输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.

示例 2:

输入:l1 = [0], l2 = [0]
输出:[0]

示例 3:

输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]

提示:

  • 每个链表中的节点数在范围 [1, 100] 内
  • 0 <= Node.val <= 9
  • 题目数据保证列表表示的数字不含前导零

方法1:(1ms)

    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode head = new ListNode();
        ListNode temp = head;
        int more = 0;
        int res = 0;
        while (!(l1 == null && l2 == null)){
            res = (l1 != null? l1.val : 0) + (l2 != null? l2.val : 0) + more;
            if (res > 9){
                res = res - 10;
                more = 1;
            }else {
                more = 0;
            }
            ListNode newNode = new ListNode(res);
            temp.next = newNode;
            temp = temp.next;
            if (l1.next != null){
                l1 = l1.next;
            }
            if (l2.next != null){
                l2 = l2.next;
            }
        }
        if (more == 1){
            temp.next = new ListNode(more);
        }
        return head.next;
    }

59. 合并两个有序链表 ① √-

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

示例 1:

输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]

示例 2:

输入:l1 = [], l2 = []
输出:[]

示例 3:

输入:l1 = [], l2 = [0]
输出:[0]

提示:

  • 两个链表的节点数目范围是 [0, 50]
  • -100 <= Node.val <= 100
  • l1 和 l2 均按 非递减顺序 排列

方法1:(0ms)

    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        if (list1 == null && list2 == null) {
            return null;
        } else if (list1 == null && list2 != null) {
            return list2;
        } else if (list1 != null && list2 == null) {
            return list1;
        }
        ListNode head = new ListNode();
        ListNode left = list1;
        ListNode right = list2;
        ListNode temp = head;
        while (left != null && right != null) {
            if (left.val < right.val) {
                temp.next = left;
                left = left.next;
            } else {
                temp.next = right;
                right = right.next;
            }
            temp = temp.next;
        }
        if (left == null) {
            temp.next = right;
        } else if (right == null) {
            temp.next = left;
        }
        return head.next;
    }

方法2:(0ms  递归)

    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        if (list1 == null) {
            return list2;
        }
        else if (list2 == null) {
            return list1;
        }
        else if (list1.val < list2.val) {
            list1.next = mergeTwoLists(list1.next, list2);
            return list1;
        }
        else {
            list2.next = mergeTwoLists(list1, list2.next);
            return list2;
        }
    }

60. 随机链表的复制 ②

61. 反转链表II ② ×

给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。

示例 1:

输入:head = [1,2,3,4,5], left = 2, right = 4
输出:[1,4,3,2,5]

示例 2:

输入:head = [5], left = 1, right = 1
输出:[5]

提示:

  • 链表中节点数目为 n
  • 1 <= n <= 500
  • -500 <= Node.val <= 500
  • 1 <= left <= right <= n

力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

方法2:(0ms)

    public ListNode reverseBetween(ListNode head, int m, int n) {
        // 定义一个dummyHead, 方便处理
        ListNode dummyHead = new ListNode(0);
        dummyHead.next = head;

        // 初始化指针
        ListNode g = dummyHead;
        ListNode p = dummyHead.next;

        // 将指针移到相应的位置
        for(int step = 0; step < m - 1; step++) {
            g = g.next; p = p.next;
        }

        // 头插法插入节点
        for (int i = 0; i < n - m; i++) {
            ListNode removed = p.next;
            p.next = p.next.next;

            removed.next = g.next;
            g.next = removed;
        }

        return dummyHead.next;
    }

作者:贾卷积
链接:https://leetcode.cn/problems/reverse-linked-list-ii/solutions/138910/java-shuang-zhi-zhen-tou-cha-fa-by-mu-yi-cheng-zho/

62. K个一组翻转链表 ③

63. 删除链表的倒数第N个结点 ② √-

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

示例 1:

输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]

示例 2:

输入:head = [1], n = 1
输出:[]

示例 3:

输入:head = [1,2], n = 1
输出:[1]

提示:

  • 链表中结点的数目为 sz
  • 1 <= sz <= 30
  • 0 <= Node.val <= 100
  • 1 <= n <= sz

进阶:你能尝试使用一趟扫描实现吗?

方法1:(0ms)

    public ListNode removeNthFromEnd(ListNode head, int n) {
        if (head.next == null && n == 1){
            return null;
        }
        int count = 1;
        ListNode temp = head;
        while (temp.next != null){
            count++;
            temp = temp.next;
        }
        if (n == count){
            return head.next;
        }else {
            int cnt = 1;
            temp = head;
            while (cnt < count - n) {
                cnt++;
                temp = temp.next;
            }
            temp.next = temp.next.next;
            return head;
        }
    }

 方法2:(0ms)

解题思路:
整体思路是让前面的指针先移动 n 步,之后前后指针共同移动直到前面的指针到尾部为止
首先设立预先指针 pre
设预先指针 pre 的下一个节点指向 head,设前指针为 start,后指针为 end,二者都等于 pre
start 先向前移动n步
之后 start 和 end 共同向前移动,此时二者的距离为 n,当 start 到尾部时,end 的位置恰好为倒数第 n 个节点
因为要删除该节点,所以要移动到该节点的前一个才能删除,所以循环结束条件为 start.next != null
删除后返回 pre.next,为什么不直接返回 head 呢,因为 head 有可能是被删掉的点
时间复杂度:O(n)

作者:画手大鹏
链接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list/solutions/7803/hua-jie-suan-fa-19-shan-chu-lian-biao-de-dao-shu-d/
 

    //通过快慢指针来解决,类似于你要删除中间元素的题
    public ListNode removeNthFromEnd(ListNode head, int n) {
        //定义一个伪节点,用于返回结果
        ListNode dumpy = new ListNode(0);
        dumpy.next = head;
        //定义一个快指针,指向伪节点,用于遍历链表
        ListNode prev = dumpy;
        //定一个慢指针,
        ListNode tail = dumpy;
        //让快指针先移动 n 步
        while(n >0){
            prev = prev.next;
            n--;
        }
        //只要快指针不指向空,就继续循环
        while(prev.next !=null){
            //让快慢指针同时移动
            tail = tail.next;
            prev = prev.next;
        }
        //这时慢指针移动到的位置就是,要删除节点的前一个节点
        //所以只要删除当前节点的下一个节点
        tail.next = tail.next.next;
        //返回为指针指向的头节点
        return dumpy.next;
    }

64. 删除排序链表中的重复元素II ②  √-

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

示例 1:

输入:head = [1,2,3,3,4,4,5]
输出:[1,2,5]

示例 2:

输入:head = [1,1,1,2,3]
输出:[2,3]

提示:

  • 链表中节点数目在范围 [0, 300] 内
  • -100 <= Node.val <= 100
  • 题目数据保证链表已经按升序 排列

方法1:(0ms)

    public static ListNode deleteDuplicates(ListNode head) {
        if (head == null || head.next == null){
            return head;
        }
        ListNode pre = new ListNode(0);
        pre.next = head;
        ListNode newNode = pre;
        while (head != null && head.next != null){
            if (head.val != head.next.val) {   // 用值做比较,而不是两个节点做比较,节点一定不相等
                head = head.next;
                pre = pre.next;
            }else {
                while (head.next != null && head.next.val == head.val){  // 用值做比较
                    head = head.next;
                }
                head = head.next;
                pre.next = head;
            }
        }
        return newNode.next;
    }

解题思路:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

65. 旋转链表 ② √-

给你一个链表的头节点 head ,旋转链表,将链表每个节点向右移动 k 个位置。

示例 1:

输入:head = [1,2,3,4,5], k = 2
输出:[4,5,1,2,3]

示例 2:

输入:head = [0,1,2], k = 4
输出:[2,0,1]

提示:

  • 链表中节点的数目在范围 [0, 500] 内
  • -100 <= Node.val <= 100
  • 0 <= k <= 2 * 109

方法1:(1842ms)

    public static ListNode rotateRight(ListNode head, int k) {
        if (head == null || head.next == null || k == 0){
            return head;
        }
        ListNode temp = head;
        ListNode pre = new ListNode(0);
        pre.next = head;
        int cnt = 0;
        while (cnt < k - 1){
            if (temp.next == null){
                temp = head;
            }else {
                temp = temp.next;
            }
            cnt++;
        }
        while (temp != null){
            pre = pre.next;
            temp = temp.next;
        }
        ListNode cur = pre;
        while (pre.next != null){
            pre = pre.next;
        }
        while (head != cur){
            pre.next = new ListNode(head.val);
            pre = pre.next;
            head = head.next;
        }
        return cur;
    }

方法2:(0ms)

    public static ListNode rotateRight(ListNode head, int k) {
        if(head == null || head.next == null || k <= 0) {
            return head;
        }
        int n = 0;
        ListNode p = head;
        while(p != null) {
            p = p.next;
            n++;
        }
        k = k%n;
        if(k == n || k == 0) {
            return head;
        }
        ListNode slow = head , fast = head;
        for(int i=0; i<n-1; i++) {
            if(i >= k) {
                slow = slow.next;
            }
            fast = fast.next;
        }

        ListNode ans = head;
        ans = slow.next; //slow为新链表头结点的前一个节点 
        slow.next = null; //在旧链表中将新链表头结点与之前的节点斩断
        fast.next = head;  //旧链表的尾节点连接上旧链表的头结点
        return ans;
    }

66. 分隔链表 ② √

给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。

你应当 保留 两个分区中每个节点的初始相对位置。

示例 1:

输入:head = [1,4,3,2,5,2], x = 3
输出:[1,2,2,4,3,5]

示例 2:

输入:head = [2,1], x = 2
输出:[1,2]

提示:

  • 链表中节点的数目在范围 [0, 200] 内
  • -100 <= Node.val <= 100
  • -200 <= x <= 200

方法1:(0ms)

    public static ListNode partition(ListNode head, int x) {
        if (head == null || head.next == null){
            return head;
        }
        ListNode pre = new ListNode(0);
        pre.next = head;
        ListNode temp = head;
        ListNode newList = pre;
        while (temp != null && temp.val < x){
            temp = temp.next;
            pre = pre.next;
        }
        if (temp == null){
            return head;
        }
        ListNode cur = temp;
        ListNode newPre = new ListNode(0);
        newPre.next = temp;
        ListNode newCur = cur;
        while (cur != null){
            if (cur.val < x){
                newCur = cur.next;
                pre.next = new ListNode(cur.val);
                pre = pre.next;
                cur = newCur;
                newPre.next = cur;
            }else {
                cur = cur.next;
                newPre = newPre.next;
            }
        }
        pre.next = temp;
        return newList.next;
    }

方法2:(0ms):力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

    public ListNode partition(ListNode head, int x) {
        ListNode smlDummy = new ListNode(0), bigDummy = new ListNode(0);
        ListNode sml = smlDummy, big = bigDummy;
        while (head != null) {
            if (head.val < x) {
                sml.next = head;
                sml = sml.next;
            } else {
                big.next = head;
                big = big.next;
            }
            head = head.next;
        }
        sml.next = bigDummy.next;
        big.next = null;
        return smlDummy.next;
    }

作者:Krahets
链接:https://leetcode.cn/problems/partition-list/solutions/2362068/86-fen-ge-lian-biao-shuang-zhi-zhen-qing-hha7/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

67. LRU缓存 ②

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

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

相关文章

【目标检测】图解 YOLOv3 的网络结构(Darknet-53 作为 backbone)

到了 YOLOv3&#xff0c;backbone 从 YOLOv2 的 Darknet-19 升级到了 Darknet-53。 下面一张完整的结构示意图来一起理解一下 YOLOv3 的网络结构。 我们怎么理解最后输出的 3 个特征图&#xff08;feature map&#xff09;的这个 255&#xff1f; 同 YOLOv2 一样&#xff0c;…

常见传感器的原理 和 常见滤波算法实现

阅读引言&#xff1a; 分析常见的传感器的电路原理、向大家提供一些ADC常见的滤波算法的实现, 介绍声、光、热、电、力、气和磁传感器的大致工作原理。 目录 一、常见传感器工作原理 1.声音传感器-动圈&电容咪头 2.光传感器-光敏电阻 3.热传感器-热电偶 4.电传感器-电…

YOLOv8改进 | 主干篇 | 利用图像分割网络UNetV2改善图像分割检测性能(全网独家首发)

一、本文介绍 本文给大家带来的改进机制是利用图像分割网络UNetV2的主干来改进我们的YOLOv8分割模型&#xff08;本文的内容虽然YOLOv8所有的功能的用户都能使用&#xff0c;但是还是建议分割的用户使用&#xff09;&#xff0c;U-Net v2 旨在改进医学图像分割的性能&#xff…

Spring-Gateway服务网关

一、网关介绍 1. 为什么需要网关 Gateway网关是我们服务的守门神&#xff0c;所有微服务的统一入口。 网关的核心功能特性&#xff1a; 请求路由 权限控制 限流 架构图&#xff1a; 权限控制&#xff1a;网关作为微服务入口&#xff0c;需要校验用户是是否有请求资格&am…

Zerotier 异地组网方案初探

前言 我之前想要异地组网的话&#xff0c;一般都采用内网穿透的方法&#xff0c;但是这个内网穿透有弊端就是都是要通过公网服务器转发流量&#xff0c;对于大流量的传输就比较不方便&#xff0c;我发现了Zerotier 这个工具非常的好用&#xff0c;是基于p2p的 这是一个类似于…

【SpringBoot3+Mybatis】框架快速搭建

文章目录 GitHub 项目一、依赖二、 配置文件三、启动类四、SpringBoot3兼容Druid报错五、工具类5.1 结果封装类5.2 解决枚举类5.3 MD5加密工具类 GitHub 项目 springboot-part——springboot-integrate-07 Mybatis-plus版完整CRUD项目文档记录&#xff1a; 【SpringBoot3Myba…

【项目实践Day06】异步请求与同步请求+Ajax+微信小程序上实现发送异步请求

什么是同步和异步 同步 在主线程上排队执行的任务&#xff0c;只有前一个任务执行完毕&#xff0c;才能继续执行下一个任务。也就是一旦调用开始&#xff0c;就必须等待其返回结果&#xff0c;程序的执行顺序和任务排列顺序一致。客户端必须等待服务器端的响应。在等待的期间客…

【保姆级】前端使用node.js基础教程

文章目录 安装和版本管理&#xff1a;npm 命令&#xff08;Node 包管理器&#xff09;&#xff1a;运行 Node.js 脚本&#xff1a;调试和开发工具&#xff1a;其他常用命令&#xff1a;模块管理&#xff1a;包管理&#xff1a;调试工具&#xff1a;异步编程和包管理&#xff1a…

kafka2.x版本配置SSL进行加密和身份验证

背景&#xff1a;找了一圈资料&#xff0c;都是东讲讲西讲讲&#xff0c;最后我还没搞好&#xff0c;最终决定参考官网说明。 官网指导手册地址&#xff1a;Apache Kafka 需要预备的知识&#xff0c;keytool和openssl 关于keytool的参考&#xff1a;keytool的使用-CSDN博客 …

【漏洞复现】正方教学管理信息服务平台ReportServer存在任意文件读取

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

wireshark数据捕获实验简述

Wireshark是一款开源的网络协议分析工具&#xff0c;它可以用于捕获和分析网络数据包。是一款很受欢迎的“网络显微镜”。 实验拓扑图&#xff1a; 实验基础配置&#xff1a; 服务器&#xff1a; ip:172.16.1.88 mask:255.255.255.0 r1: sys sysname r1 undo info enable in…

HCIP作业

实验要求&#xff1a; 1、R6为ISP&#xff0c;接口IP地址均为公有地址&#xff0c;该设备只能配置IP地址&#xff0c;之后不能再对其进行任何配置&#xff1b; 2、R1-R5为局域网&#xff0c;私有IP地址192.168.1.0/24&#xff0c;请合理分配&#xff1b; 3、R1、R2、R4&#x…

java数据结构与算法刷题-----LeetCode135. 分发糖果

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 文章目录 1. 左右遍历2. 进阶&#xff1a;常数空间遍历&#xff0c;升序降…

LabVIEW NV色心频率扫描

LabVIEW NV色心频率扫描 通过LabVIEW软件开发一个能够实现对金刚石氮空位&#xff08;Nitrogen-Vacancy&#xff0c;NV&#xff09;色心的频率扫描系统。系统通过USB协议与硬件设备通信&#xff0c;对NV色心进行高精度的频率扫描&#xff0c;满足了频率在2.6 GHz到3.2 GHz范围…

使用DMA方式控制串口

本身DMA没什么问题&#xff0c;但是最后用GPIOB点灯&#xff0c;就是点不亮。 回到原来GPIO点灯程序&#xff0c;使用GPIOB就是不亮&#xff0c;替换为GPIOA就可以&#xff0c;简单问题总是卡得很伤。

微信小程序的配置文件使用说明:

在上一文中学习开发小程序的起航日记&#xff0c;我们准备好了开发小程序时所需的环境和准备工作&#xff0c;同时也简单的了解了一下小程序的项目结构组成。 这一章&#xff0c;我们主要对小程序的配置文件进行学习。 文章目录 小程序_配置文件1.json2.app.jsonpages 属性wind…

C++:类和对象(上篇)

目录&#xff1a; 一&#xff1a;面向对象和过程的介绍 二&#xff1a;类的引入 三&#xff1a;类的定义 四&#xff1a;类的访问限定符以及封装 五&#xff1a;类的作用域 六&#xff1a;类的实例化 七&#xff1a;类对象大小的计算 八&#xff1a;类成员函数的this指…

DolphinScheduler运维-页面加载缓慢

一、问题描述 DolphinScheduler调度平台的UI界面加载缓慢,项目中的任务实例加载时间过长,需要解决这个问题,提高DolphinScheduler平台UI页面的加载速度。 二、原因分析 经过分析发现,任务实例过多是导致UI加载缓慢的主要原因。由于任务实例无法直接删除,根据文档了解到需…

基于docker+rancher部署Vue项目的教程

基于dockerrancher部署Vue的教程 前段时间总有前端开发问我Vue如何通过docker生成镜像&#xff0c;并用rancher上进行部署&#xff1f;今天抽了2个小时研究了一下&#xff0c;给大家记录一下这个过程。该部署教程适用于Vue、Vue2、Vue3等版本。 PS&#xff1a;该教程基于有一定…

UART动态调整接收时钟

文章目录 一、UART接收模块误码率二、接收时钟动态纠正方法2.1、过采样2.2、上板效果 一、UART接收模块误码率 由于发送端和接收端存在一定的频率误差&#xff0c;随着时间的推移&#xff0c;累计误差不断增加&#xff0c;从而产生亚稳态现象&#xff0c;会导致误码&#xff0…