力扣链表篇

news2025/2/28 5:06:52

以下刷题思路来自代码随想录以及官方题解

文章目录

      • 203.移除链表元素
      • 707.设计链表
      • 206.反转链表
      • 24.两两交换链表中的节点
      • 19.删除链表的倒数第N个节点
      • 面试题 02.07. 链表相交
      • 142.环形链表II

203.移除链表元素

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

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

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

输入:head = [7,7,7,7], val = 7
输出:[]
/**
 * Definition for singly-linked list.
 * public class ListNode {
 * int val;
 * ListNode next;
 * ListNode() {}
 * ListNode(int val) { this.val = val; }
 * ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode removeElements(ListNode head, int val) {

        //首先解决头节点不为空,为val的情况
        while (head != null && head.val == val) {
            head = head.next;
        }

        // 如果头节点为空
        if (head == null) {
            return head;
        }

        ListNode pre = head;
        ListNode cur = head.next;

        while (cur != null) {
            // 判断值相等
            if (cur.val == val) {
                pre.next = cur.next;
            } else {
                pre = cur;
            }
            cur = cur.next;
        }

        return head;
    }
}

707.设计链表

你可以选择使用单链表或者双链表,设计并实现自己的链表。

单链表中的节点应该具备两个属性:valnextval 是当前节点的值,next 是指向下一个节点的指针/引用。

如果是双向链表,则还需要属性 prev 以指示链表中的上一个节点。假设链表中的所有节点下标从 0 开始。

实现 MyLinkedList 类:

MyLinkedList() 初始化 MyLinkedList 对象。
int get(int index) 获取链表中下标为 index 的节点的值。如果下标无效,则返回 -1 。
void addAtHead(int val) 将一个值为 val 的节点插入到链表中第一个元素之前。在插入完成后,新节点会成为链表的第一个节点。
void addAtTail(int val) 将一个值为 val 的节点追加到链表中作为链表的最后一个元素。
void addAtIndex(int index, int val) 将一个值为 val 的节点插入到链表中下标为index 的节点之前。如果 index 等于链表的长度,那么该节点会被追加到链表的末尾。如果 index 比长度更大,该节点将 不会插入 到链表中。
void deleteAtIndex(int index) 如果下标有效,则删除链表中下标为 index 的节点。

输入
["MyLinkedList", "addAtHead", "addAtTail", "addAtIndex", "get", "deleteAtIndex", "get"]
[[], [1], [3], [1, 2], [1], [1], [1]]
输出
[null, null, null, null, 2, null, 3]

解释
MyLinkedList myLinkedList = new MyLinkedList();
myLinkedList.addAtHead(1);
myLinkedList.addAtTail(3);
myLinkedList.addAtIndex(1, 2);    // 链表变为 1->2->3
myLinkedList.get(1);              // 返回 2
myLinkedList.deleteAtIndex(1);    // 现在,链表变为 1->3
myLinkedList.get(1);              // 返回 3
public class ListNode {
    int val;
    ListNode next;

    ListNode() {
    }

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

class MyLinkedList {

    // 存储链表中节点个数
    int size;

    // 虚拟头节点
    ListNode head;

    public MyLinkedList() {
        size = 0;
        head = new ListNode(0);
    }

    public int get(int index) {
        if (index < 0 || index >= size) {
            return -1;
        }
        ListNode cur = head;
        // 直接遍历到该结点
        for (int i = 0; i <= index; i++) {
            cur = cur.next;
        }
        return cur.val;
    }

    public void addAtHead(int val) {
        addAtIndex(0, val);
    }

    public void addAtTail(int val) {
        addAtIndex(size, val);
    }

    public void addAtIndex(int index, int val) {
        if (index > size) {
            return;
        }
        if (index < 0) {
            index = 0;
        }
        // 因为需要插入所以size++
        size++;
        // 因为是单链表,所以需要找到插入位置的前节点
        ListNode pre = head;
        for (int i = 0; i < index; i++) {
            pre = pre.next;
        }

        ListNode newNode = new ListNode(val);
        // 这里顺序至关重要
        newNode.next = pre.next;
        pre.next = newNode;

    }

    public void deleteAtIndex(int index) {
        if (index < 0 || index >= size) {
            return;
        }
        size--;
        if (index == 0) {
            head = head.next;
            return;
        }

        ListNode pre = head;
        for (int i = 0; i < index; i++) {
            pre = pre.next;
        }
        pre.next = pre.next.next;

    }
}

206.反转链表

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

输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        ListNode preNode = null;
        ListNode curNode = head;
        ListNode temp = null;

        while(curNode != null){
        	//暂存下一个节点
            temp = curNode.next;
            //反转箭头
            curNode.next = preNode;
            
            preNode =  curNode;
            curNode = temp;
        }

        return preNode;
    }
}

24.两两交换链表中的节点

给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即只能进行节点交换)。

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

输入:head = []
输出:[]

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

这道题我没看懂,过后再来理解一下。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode swapPairs(ListNode head) {

        if(head == null || head.next == null){
            return head;
        }
        // 获取当前节点的下一个节点
        ListNode next = head.next;
        // 进行递归
        ListNode newNode = swapPairs(next.next);
        // 这里进行交换
        next.next = head;
        head.next = newNode;

        return next;
    }
}

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

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

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

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

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

这道题的思路很好理解,点赞!

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        // 创建一个虚拟头节点pre,将其next指针指向head
        ListNode pre = new ListNode(0);
        pre.next = head;
        // 定义两个指针start和end,都指向pre
        ListNode start = pre, end = pre;
        // 将start指针向前移动n个节点,即start和end之间相隔n个节点
        while(n != 0) {
            start = start.next;
            n--;
        }
        // 同时移动start和end指针,直到start指向最后一个节点
        while(start.next != null) {
            start = start.next;
            end = end.next;
        }
        // 删除倒数第n个节点,即将end的next指针指向end.next.next
        end.next = end.next.next;
        // 返回删除节点后的链表头节点
        return pre.next;
    }
}

下面是力扣官方题解真的通俗移动,膜拜!

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummy = new ListNode(0, head);
        int length = getLength(head);
        ListNode cur = dummy;
        for (int i = 1; i < length - n + 1; ++i) {
            cur = cur.next;
        }
        cur.next = cur.next.next;
        ListNode ans = dummy.next;
        return ans;
    }

    public int getLength(ListNode head) {
        int length = 0;
        while (head != null) {
            ++length;
            head = head.next;
        }
        return length;
    }
}

面试题 02.07. 链表相交

给你两个单链表的头节点 headAheadB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。

在这里插入图片描述

输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Intersected at '8'
解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A[4,1,8,4,5],链表 B[5,0,1,8,4,5]。
在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。

输入:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出:Intersected at '2'
解释:相交节点的值为 2 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A[0,9,1,2,4],链表 B[3,2,4]。
在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。

输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
输出:null
解释:从各自的表头开始算起,链表 A[2,6,4],链表 B[1,5]。
由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。
这两个链表不相交,因此返回 null

对于这道题,同样使用哈希表来解决。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 * int val;
 * ListNode next;
 * ListNode(int x) {
 * val = x;
 * next = null;
 * }
 * }
 */
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        //HashSet是一个没有重复元素的集合
        Set<ListNode> set = new HashSet<ListNode>();
        ListNode temp = headA;
        while(temp != null){
            set.add(temp);
            temp = temp.next;
        }

        temp = headB;
        while(temp!=null){
            if(set.contains(temp)){
                return temp;
            }
            temp = temp.next;
        }
        return null;
    }
}

142.环形链表II

给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

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

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

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

我们遍历链表中的每个节点,并将它记录下来;一旦遇到了此前遍历过的节点,就可以判定链表中存在环。借助哈希表可以很方便地实现。

/**
 * Definition for singly-linked list.
 * class ListNode {
 * int val;
 * ListNode next;
 * ListNode(int x) {
 * val = x;
 * next = null;
 * }
 * }
 */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        Set<ListNode> set = new HashSet<>();
        while (head != null) {
            if (set.contains(head)) {
                return head;
            } else {
                set.add(head);
            }
            head = head.next;
        }
        return null;
    }
}

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

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

相关文章

NPS配置内网穿透-Windows,PVE

Windows和PVE的区别就是下载客户端的时候一个选windows-amd64(64位的电脑)另一个选 linux-amd64(64位电脑),386对应的是32位的电脑. Releases ehang-io/nps (github.com) PVE的安装参考的是以下视频安装.利用PVE虚拟机&#xff0c;来打造属于自己的All In One系统吧&#xf…

ssm747普通话培训信息管理系统设计与实现(源码+调试+LW)

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。今天给大家介绍一篇基于ssm普通话培训信息管…

北航复试知识点总结

2024.2.25 住行 报道+机试+两天面试=4天 面试流程 (每个人大概20min,早一点到考场!) 形式:5位老师(一记录,四提问) 老师 陆峰 办公地址:北京航空航天大学新主楼H1033 电子邮箱: lufeng@buaa.edu.cn 个人主页:http://shi.buaa.edu.cn/lufeng/ 面试礼仪 于无形中…

【Python笔记-设计模式】代理模式

一、说明 代理模式是一种结构型设计模式&#xff0c;提供对象的替代品或其占位符。代理控制着对于原对象的访问&#xff0c;并允许在将请求提交给对象前后进行一些处理。 (一) 解决问题 控制对对象的访问&#xff0c;或在访问对象前增加额外的功能或控制访问 (二) 使用场景…

【前端素材】推荐优质后台管理系统Uena平台模板(附源码)

一、需求分析 后台管理系统&#xff08;或称作管理后台、管理系统、后台管理平台&#xff09;是一种专门用于管理网站、应用程序或系统后台运营的软件系统。它通常由一系列功能模块组成&#xff0c;为管理员提供了管理、监控和控制网站或应用程序的各个方面的工具和界面。以下…

银河麒麟操作系统安装Anaconda

下载 首先确认需要安装的版本 uname -maarch64https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/?CM&OD 在上面网址中下载相应的版本 下载后&#xff0c;上传到服务器 安装 bash Anaconda3-2023.09-0-Linux-aarch64.sh 点击enter&#xff0c;继续 输入yes同意许…

【Python】Windows本地映射远程Linux服务器上的端口(解决jupyter notebook无法启动问题)

创作日志&#xff1a; 学习深度学习不想在本地破电脑上再安装各种软件&#xff0c;我就用实验室的服务器配置环境&#xff0c;启动jupyter notebook时脑子又瓦特了&#xff0c;在自己Windows电脑上打开服务器提供的网址&#xff0c;那肯定打不开啊&#xff0c;以前在其它电脑上…

【Linux】部署前后端分离项目---(Nginx自启,负载均衡)

目录 前言 一 Nginx&#xff08;自启动&#xff09; 2.1 Nginx的安装 2.2 设置自启动Nginx 二 Nginx负载均衡tomcat 2.1 准备两个tomcat 2.1.1 复制tomcat 2.1.2 修改server.xml文件 2.1.3 开放端口 2.2 Nginx配置 2.2.1 修改nginx.conf文件 2.2.2 重启Nginx服务 2…

Python爬虫之点触验证码的识别

点触验证码的识别 除了极验验证码&#xff0c;还有另一种常见且应用广泛的验证码&#xff0c;即点触验证码。 可能你对这个名字比较陌生&#xff0c;但是肯定见过类似的验证码&#xff0c;比如 12306 就是典型的点触验证码。 直接点击图中符合要求的图。所有答案均正确&#…

mapbox动态的箭头指示(视觉效果上是这样)

贴个群号 WebGIS学习交流群461555818&#xff0c;欢迎大家。 成果图 原理 这个一般用于一些比如类似转移路线的指示&#xff0c;这个方案其实是一种视觉上的欺骗&#xff0c;实际上仔细观察箭头并没有动&#xff0c;在视觉上看起来好像是箭头在动&#xff0c;营造出一种动态…

提高SQL查询效率1——验证索引的有效性

在大数据量的SQL表中&#xff0c;往往会出现一些查询效率低的问题&#xff0c;耗时&#xff0c;如果解决这里问题呢&#xff1f;本文主要探索索引在提高SQL效率的有效性。 目录 1、创建数据表 2、为建立索引之前&#xff0c;查看执行效率 3、给Name建立索引 4、查看索引 1、…

Facebook的数字社交使命:连接世界的下一步

在数字化时代&#xff0c;社交媒体已成为人们生活的重要组成部分&#xff0c;而Facebook作为其中最具影响力的平台之一&#xff0c;一直以来都在努力履行着自己的使命——连接世界。然而&#xff0c;随着时代的变迁和技术的发展&#xff0c;Facebook正在不断探索着连接世界的下…

多目标追踪概述

1. 目标跟踪分类 单目标跟踪&#xff1a;在视频的初始帧画面上框出单个目标&#xff0c;预测后续帧中该目标的大小与位置多目标跟踪&#xff1a;追踪多个目标的大小和位置&#xff0c;且每一帧中目标的数量和位置都可能变化 2. 多目标跟踪目前的主要问题 形态变化&#xff1a…

自定义el-upload 上传文件

前言 最近在做一个文件上传的功能&#xff0c;后端接口写好了、发现前端上传文件的页面不会写……&#xff08;我很笨的&#xff09;然后我就找啊找发现element有个组件是<el-upload/>能直接上传文件。我就想直接用拿来改改改成自己想要的&#xff0c;可是就是这样我花了…

Elasticsearch:了解人工智能搜索算法

作者&#xff1a;来自 Elastic Jessica Taylor, Aditya Tripathi 人工智能工具无处不在&#xff0c;其原因并不神秘。 他们可以执行各种各样的任务并找到许多日常问题的解决方案。 但这些应用程序的好坏取决于它们的人工智能搜索算法。 简单来说&#xff0c;人工智能搜索算法是…

如何搭建零售行业经营分析体系?

​怎么搭建零售行业的经营分析体系&#xff1f; 整体思路就是&#xff1a;利用数据中台基于业务全价值链的数据沉淀&#xff0c;借助大数据技术进行采集、计算、存储和加工&#xff0c;同时统一数据建模与治理&#xff0c;构建数据资产&#xff0c;充分挖掘数据&#xff0c;实…

从事通讯信息类职业岗位的任职资格

通讯信息工程师&#xff0c;主要是移动核心网和固网核心网的工程切割和维护网络安全的专业工作&#xff0c;主要负责IP数据、省网和地域网络的维护。一切跟互联网打交道的事情&#xff0c;都跟这个有关系&#xff0c;都是通讯信息类岗位的工作。从事这种工作&#xff0c;需要付…

IOBR2 更新(学习自备)

IOBR查看其收录的相关基因集(自备)_肿瘤 tme特征 iobr-CSDN博客 IOBR2&#xff1a;多维度解析肿瘤微环境 - 知乎 (zhihu.com) 学习手册&#xff1a;https://iobr.github.io/book/ &#xff08;里面有详细教程&#xff09; 系统综合的分析工具&#xff08;Immuno-Oncology Bi…

flutter简单的MethodChannel通道Demo(引入调用小红书sdk)

flutter端创建MethodChannel类 import package:flutter/services.dart;//MethodChannel const methodChannel const MethodChannel(com.flutter.demo.MethodChannel);class FlutterMethodChannel {/** MethodChannel flutter给原生发信息* 在方法通道上调用方法invokeMethod*…

基于YOLOv8深度学习+Pyqt5的电动车头盔佩戴检测系统

wx供重浩&#xff1a;创享日记 对话框发送&#xff1a;225头盔 获取完整源码源文件已标注的数据集&#xff08;1463张&#xff09;源码各文件说明配置跑通说明文档 若需要一对一远程操作在你电脑跑通&#xff0c;有偿89yuan 效果展示 基于YOLOv8深度学习PyQT5的电动车头盔佩戴检…