《代码随想录》刷题笔记——链表篇【java实现】

news2024/11/25 11:43:25

链表节点定义

public class ListNode {
    // 结点的值
    int val;

    // 下一个结点
    ListNode next;

    // 节点的构造函数(无参)
    public ListNode() {
    }

    // 节点的构造函数(有一个参数)
    public ListNode(int val) {
        this.val = val;
    }

    // 节点的构造函数(有两个参数)
    public ListNode(int val, ListNode next) {
        this.val = val;
        this.next = next;
    }
}

*移除链表节点

题目链接:https://leetcode.cn/problems/reverse-linked-list/

【思路】

有时候增加一个虚拟节点,可以让后面的操作都一致

public static ListNode removeElements(ListNode head, int val) {
    if (head == null) {
        return null;
    }

    // 增加一个虚拟节点
    ListNode virtualNode = new ListNode();
    virtualNode.next = head;

    ListNode cur = virtualNode;
    ListNode next = cur.next;
    while (next != null) {
        if (next.val == val) {
            cur.next = next.next;
        } else {
            cur = next;
        }
        next = cur.next;
    }

    return virtualNode.next;
}

*反转链表

双指针法

  • 时间复杂度: O(n)
  • 空间复杂度: O(1)

在这里插入图片描述

public static ListNode reverseList(ListNode head) {
    ListNode cur = head;
    ListNode pre = null;
    ListNode temp = null;
    while (cur != null) {
        temp = cur.next;
        cur.next = pre;
        pre = cur;
        cur = temp;
    }
    return pre;
}

递归法

  • 时间复杂度: O(n)
  • 空间复杂度: O(n)

这里的逻辑和双指针法的逻辑是一样的,只是实现方式是递归,那为什么空间复杂度更高呢?

答:因为递归本质上是一种函数调用,在每一次递归调用时,都会在函数栈中分配一段内存空间来保存函数的局部变量、返回地址以及参数等信息。因此,递归实现相对于循环实现的空间复杂度更高,会占用更多的内存空间。尤其是在递归深度较大的情况下,可能会导致栈溢出等问题。而使用循环实现通常不需要使用额外的栈空间,因此循环实现的空间复杂度比递归实现要低

public static ListNode reverseList1(ListNode head) {
    return reverse(null, head);
}

public static ListNode reverse(ListNode pre, ListNode cur) {
    if (cur != null) {
        ListNode temp = cur.next;
        cur.next = pre;
        pre = reverse(cur, temp);
    }
    return pre;
}

*两两交换链表中的节点

https://leetcode.cn/problems/swap-nodes-in-pairs/

  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

在这里插入图片描述

public static ListNode swapPairs(ListNode head) {
    // 如果链表中没有元素 或者 只有一个元素,直接返回就行
    if (head == null || head.next == null) {
        return head;
    }

    // 增加一个虚拟头节点
    ListNode virtualNode = new ListNode();
    virtualNode.next = head;
    ListNode last = virtualNode;
    ListNode cur = head;
    ListNode next = cur.next;
    ListNode temp = null;

    while (next != null) {
        // 交换
        temp = next.next;
        cur.next = next.next;
        next.next = cur;
        last.next = next;

        // 指针移动到新的位置
        last = cur;
        cur = temp;
        if (cur != null) {
            next = cur.next;
        } else {
            break;
        }
    }
    return virtualNode.next;
}

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

https://leetcode.cn/problems/remove-nth-node-from-end-of-list/submissions/

快慢指针法

在这里插入图片描述

/**
 * 让快指针比慢指针先移动 n 步
 *
 * @param head
 * @param n
 * @return
 */
public static ListNode removeNthFromEnd(ListNode head, int n) {
    ListNode virtual = new ListNode();
    virtual.next = head;
    // 让快指针先移动到n个节点
    ListNode fast = virtual;
    for (int i = 0; i < n; i++) {
        if (fast.next != null) {
            fast = fast.next;
        }
    }

    // slow和fast一起移动,等fast到达最后一个节点的时候,slow也就到达了要删除的节点前面的节点
    ListNode slow = virtual;
    while (fast.next != null) {
        slow = slow.next;
        fast = fast.next;
    }

    // 执行删除操作
    slow.next = slow.next.next;
    return virtual.next;
}
  • 时间复杂度: O(n)
  • 空间复杂度: O(1)

*链表相交

https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/

注意点

并不是判断val相等,而是hashcode相等

暴力求解

直接两重循环,循环两个链表

  • 时间复杂度:O(n^2)
  • 空间复杂度:O(1)

进阶解法

利用题目中的信息,已经是链表的尾部才有可能相交,可以先让一条链表前进 两条链表长度差值 的位置,最后再两条链表一起前进

在这里插入图片描述

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    ListNode cur1 = headA;
    ListNode cur2 = headB;
    int sizeA = 0;
    int sizeB = 0;

    // 统计链表A的长度
    while (cur1 != null) {
        sizeA += 1;
        cur1 = cur1.next;
    }
    // 统计链表B的长度
    while (cur2 != null) {
        sizeB += 1;
        cur2 = cur2.next;
    }
    // 回到初始位置
    cur1 = headA;
    cur2 = headB;

    // 先让元素较多的链表的指针移动一段距离
    if (sizeA > sizeB) {
        // 链表A的元素较多,先走一段距离
        for (int i = 0; i < (sizeA - sizeB); i++) {
            cur1 = cur1.next;
        }
    } else if (sizeA < sizeB) {
        for (int i = 0; i < (sizeB - sizeA); i++) {
            cur2 = cur2.next;
        }
    }

    // 两个链表同时走动
    while (cur1 != null && cur2 != null) {
        // 注意,需要的是hash值
        if (cur1.hashCode() == cur2.hashCode()) {
            return cur1;
        }
        cur1 = cur1.next;
        cur2 = cur2.next;
    }
    return null;
}
  • 时间复杂度:O(n + m)
  • 空间复杂度:O(1)

*环形链表

https://leetcode.cn/problems/linked-list-cycle-ii/

在这里插入图片描述

public static ListNode detectCycle1(ListNode head) {
    if (head == null) {
        return null;
    }

    ListNode slow = head;
    ListNode fast = head;
    ListNode node2 = null;

    // 先找到相交点
    while (slow != null && fast.next != null) {
        // slow移动一步
        slow = slow.next;
        // fast移动两步
        fast = fast.next.next;

        if (slow.hashCode() == fast.hashCode()) {
            // slow 和 fast相交
            node2 = slow;

            // 让node1从起点出发,node2从相交点出发,当node1和node2相交的时候,相交时的节点即环的入口
            ListNode node1 = head;
            while (true) {
                if (node1.hashCode() == node2.hashCode()) {
                    return node1;
                } else {
                    node1 = node1.next;
                    node2 = node2.next;
                }
            }
        }
    }
    return null;
}
  • 时间复杂度: O(n)。因为快慢指针相遇前,指针走的次数小于链表长度;快慢指针相遇后,两个node指针走的次数也小于链表长度,因此走的总次数小于 2n
  • 空间复杂度: O(1)

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

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

相关文章

【80天学习完《深入理解计算机系统》】第十四天 复习第三章

专注 效率 记忆 预习 笔记 复习 做题 欢迎观看我的博客&#xff0c;如有问题交流&#xff0c;欢迎评论区留言&#xff0c;一定尽快回复&#xff01;&#xff08;大家可以去看我的专栏&#xff0c;是所有文章的目录&#xff09;   文章字体风格&#xff1a; 红色文字表示&#…

层次分析法(matlab实现)

1.层次分析法&#xff08;AHP&#xff09; 在决策理论中&#xff0c;层次分析法是一种以数学和心理学为基础&#xff0c;组织和分析复杂决策的结构化技术&#xff0c;它代表了一种量化决策标准权重的准确方法&#xff0c;通过成对比较&#xff0c;利用个别专家的经验来估计因素…

MySQL5.7慢查询实践

总结 获取慢查询SQL 已经执行完的SQL&#xff0c;检查慢查询日志&#xff0c;日志中有执行慢的SQL正在执行中的SQL&#xff0c;show proccesslist;&#xff0c;结果中有执行慢的SQL 慢查询日志关键参数 名称解释Query_time查询消耗时间Time慢查询发生时间 分析慢查询SQL e…

【LeetCode算法系列题解】第56~60题

CONTENTS LeetCode 56. 合并区间&#xff08;中等&#xff09;LeetCode 57. 插入区间&#xff08;中等&#xff09;LeetCode 58. 最后一个单词的长度&#xff08;简单&#xff09;LeetCode 59. 螺旋矩阵 II&#xff08;中等&#xff09;LeetCode 60. 第k个排列&#xff08;困难…

ARM DIY(八)USB 调试

前言 V3s 带有一个 USB 接口&#xff0c;将其设置为 HOST 或 OTG 模式&#xff0c;这样可以用来接入键盘、鼠标等 USB 外设。 USB 简介 USB 有两种设备&#xff1a;HOST 和 USB 功能设备。 在 USB2.0 中又引入了一个新的概念 OTG&#xff0c;即设备角色可以动态切换。 切换方…

ZYNQ上的简单 FSK 基带发射器

绪论 由于某种需求需要生成正弦波&#xff0c;因此使用 C 应用程序中的sin()函数来计算单位圆的幅度值&#xff0c;然后将该幅度值转换为 AD9717 的适当 DAC 代码&#xff08;当然将每个角度值转换为弧度&#xff09;。 能够使用DAC生成简单的正弦波&#xff0c;下一个想法就是…

MSYS2 介绍、下载与安装、Pacman常用命令

一、MSYS2 介绍 MSYS2 官网&#xff1a;MSYS2 MSYS2&#xff08;Minimal SYStem 2&#xff09;是一个集成了大量的GNU工具链、工具和库的开源软件包集合。它提供了一个类似于Linux的shell环境&#xff0c;可以在Windows系统中编译和运行许多Linux应用程序和工具。 MSYS2基于…

GPT转换工具:轻松将MBR转换为GPT磁盘

为什么需要将MBR转换为GPT&#xff1f; 众所周知&#xff0c;Windows 11已经发布很长时间了。在此期间&#xff0c;许多老用户已经从Windows 10升级到Windows 11。但有些用户仍在运行Windows 10。对于那些想要升级到Win 11的用户来说&#xff0c;他们可能不确定Win 11应该使…

【初阶C语言】操作符1--对二进制的操作

前言&#xff1a;本节内容介绍的操作符&#xff0c;操作的对象是二进制位。所以前面先介绍整数的二进制位 一、二进制位介绍 1.二进制介绍 &#xff08;1&#xff09;整数的二进制表示形式有三种&#xff1a;原码、反码和补码。 &#xff08;2&#xff09;原码、反码和补码的…

TPS-MIS-DSS

TPS-MIS-DSS 业务处理系统TPS管理信息系统MIS决策支持系统DSS 业务处理系统TPS 最初级的信息系统&#xff0c;管理具体的事务 TPS是其他类型信息系统的信息产生器 处于企业系统的边界 管理信息系统MIS 对企业整体的信息进行处理 使用信息进行预测&#xff0c;控制&#xff0c;计…

一些重要的硬件概念总结

电路噪声 区分噪声和干扰 对于电子线路中所称的噪声&#xff0c;可以概括地认为&#xff0c;它是对目的信号以外所有信号的一个总称。 最初人们把造成收音机这类音响设备所发出的那些电子信号称为噪声。但是&#xff0c;一些非目的的电子信号对电子线路造成的后果并非都和声音有…

【LeetCode每日一题合集】2023.8.28-2023.9.3(到家的最少跳跃次数)

文章目录 57. 插入区间823. 带因子的二叉树解法——递推 1654. 到家的最少跳跃次数(BFS&#xff0c;&#x1f6b9;最远距离上界的证明)1761. 一个图中连通三元组的最小度数2240. 买钢笔和铅笔的方案数解法1——完全背包解法2——枚举买了几支钢笔&#xff08;推荐解法&#xff…

华为云云服务器评测|使用云耀云服务器L实例部署Portainer工具

华为云云服务器评测&#xff5c;使用云耀云服务器L实例部署Portainer工具 一、云耀云服务器L实例介绍1.1 云耀云服务器L实例简介1.2 云耀云服务器L实例特点1.3 云耀云服务器L实例使用场景 二、本次实践介绍2.1 本次实践简介2.2 Portainer简介 三、购买云耀云服务器L实例3.1 登录…

java八股文面试[数据库]——主键的类型自增还是UUID

auto_increment的优点&#xff1a; 字段长度较uuid小很多&#xff0c;可以是bigint甚至是int类型&#xff0c;这对检索的性能会有所影响。 在写的方面&#xff0c;因为是自增的&#xff0c;所以主键是趋势自增的&#xff0c;也就是说新增的数据永远在后面&#xff0c;这点对于…

QT—基于http协议的网络文件下载

1.常用到的类 QNetworkAccessManager类用于协调网络操作&#xff0c;负责发送网络请求&#xff0c;创建网络响应 QNetworkReply类表示网络请求的响应。在QNetworkAccessManager发送一个网络请求后创建一个网络响应。它提供了以下信号&#xff1a; finished()&#xff1a;完成…

Rider 中C#单元测试

使用NUnit.Framework这个包&#xff0c;没有的话可以用nuget去搜索下载。简单的进行单元测试&#xff0c;想要单元测试好像还给需要static函数&#xff0c;慢慢学学C# using System; using NUnit.Framework;namespace client {public class test{[Test]public static void test…

(二十二)大数据实战——Flume数据采集之故障转移案例实战

前言 本节内容我们完成Flume数据采集的故障转移案例&#xff0c;使用三台服务器&#xff0c;一台服务器负责采集nc数据&#xff0c;通过使用failover模式的Sink处理器完成监控数据的故障转移&#xff0c;使用Avro的方式完成flume之间采集数据的传输。整体架构如下&#xff1a;…

纯css实现奥运五环、3D平移与旋转

文章目录 前言效果图htmlcss 前言 1、不是真正的五环&#xff0c;因为通过形变得来。 2、不同电脑显示器的像素不同&#xff0c;显现的效果不同。 3、不推荐使用此方法。 4、主要通过旋转加平移的方式实现。 效果图 html <div class"olympic_rings"><span …

pt23django教程

Django的框架设计模式 MVC 设计模式 MVC 代表 Model-View-Controller&#xff08;模型-视图-控制器&#xff09; 模式。作用: **降低模块间的耦合度**(解耦) - M 模型层(Model), 主要用于对数据库层的封装 - V 视图层(View), 用于向用户展示结果 - C 控制(Controller &#x…

达梦数据库和mysql数据库获取两个坐标之间的距离

91、达梦数据库和mysql数据库获取两个坐标之间的距离 参考&#xff1a;参考 mysql 数据库&#xff1a; select st_distance_sphere(POINT(经度1,纬度1), POINT(经度2,纬度2))达梦数据库没有内置函数&#xff0c;需要自己手动创建函数 CREATE OR REPLACE FUNCTION "模式…