秋招力扣Hot100刷题总结——链表

news2024/11/24 1:35:42

1. 反转链表题目连接

  • 题目要求:给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
    在这里插入图片描述
  • 代码及思路
    • 遍历所有节点,将所有节点的next指向前一个节点
    • 由于要改变节点的next指向,而链表是单向的,因此需要使用一个节点变量先保存当前节点的next节点,然后再指向前一个节点
    • 代码
class Solution {
    public ListNode reverseList(ListNode head) {
        if(head==null||head.next==null)return head;
        ListNode pre=null;
        ListNode cur=head;
        while(head!=null){
            cur=head.next;
            head.next=pre;
            pre=head;
            head=cur;
        }
        return pre;
    }
}

2. LRU 缓存(高频) 题目链接

  • 题目要求:请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。
    实现 LRUCache 类:
    LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存
    int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1 。
    void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。
    函数 get 和 put 必须以 O(1) 的平均时间复杂度运行。
    在这里插入图片描述
  • 代码及思路
    • 使用双向链表进行实现,便于调整节点的位置
    • 需要注意的是还需要一个hashmap来存储关键字和节点的对应的关系,并且在相应的操作时不要忘记修改hashmap
    • 代码
class LRUCache {
    class DNode{
        int val;
        int key;
        DNode next;
        DNode pre;
        public DNode(){ }
        public DNode(int val,int key){
            this.val=val;
            this.key=key;
        }
    }
    DNode head;
    DNode tail;
    int size;
    int capacity;
    Map<Integer,DNode> cache=new HashMap<>();
    public LRUCache(int capacity) {
        head=new DNode();
        tail=new DNode();
        head.next=tail;
        tail.pre=head;
        this.capacity=capacity;
        size=0;
    }
    
    public int get(int key) {
        if(cache.containsKey(key)){
            DNode node=cache.get(key);
            moveToHead(node);
            return node.val;
        }
        return -1;
    }
    
    public void put(int key, int value) {
        if(cache.containsKey(key)){
            DNode node=cache.get(key);
            node.val=value;
            moveToHead(node);
        }else{
            DNode node=new DNode(value,key);
            cache.put(key,node);
            insertHead(node);
            size++;
            if(size>capacity){
                int lastKey=moveTail();
                cache.remove(lastKey);
                size--;
            }
        }
    }
    private void insertHead(DNode node){
        node.next=head.next;
        head.next.pre=node;
        head.next=node;
        node.pre=head;
    }
    private void moveToHead(DNode node){
        node.pre.next=node.next;
        node.next.pre=node.pre;
        insertHead(node);
    }
    private int moveTail(){
        int key=tail.pre.key;
        tail.pre=tail.pre.pre;
        tail.pre.next=tail;
        return key;
    }
}

/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache obj = new LRUCache(capacity);
 * int param_1 = obj.get(key);
 * obj.put(key,value);
 */

3.合并两个有序链表 题目链接

  • 题目要求:将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
    在这里插入图片描述
  • 代码及思路
    • 先遍历两个链表,选择值小的节点加入合并后的链表
    • 当其中一个链表为空时结束循环,将不为空的链表剩下节点整个加入合并后的链表
    • 最好使用一个虚拟头接点,便于处理
    • 代码
/**
 * 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 mergeTwoLists(ListNode list1, ListNode list2) {
        ListNode dumpy=new ListNode();
        ListNode cur=dumpy;
        while(list1!=null&&list2!=null){
            if(list1.val<=list2.val){
                cur.next=list1;
                list1=list1.next;
            }else{
                cur.next=list2;
                list2=list2.next;
            }
            cur=cur.next;
        }
        cur.next=list1==null?list2:list1;
        return dumpy.next;
    }
}

4. 环形链表 题目链接

  • 题目要求:给你一个链表的头节点 head ,判断链表中是否有环。
    如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。
    如果链表中存在环 ,则返回 true 。 否则,返回 false 。
    在这里插入图片描述
  • 代码及思路
    • 使用快慢指针解决问题,慢指针每次移动一步,快指针每次移动两步(相遇问题)
    • 当快慢指针相遇表明存在环
    • 代码
public class Solution {
    public boolean hasCycle(ListNode head) {
        ListNode slow=head;
        ListNode fast=head;
        while(fast!=null&&fast.next!=null){
            slow=slow.next;
            fast=fast.next.next;
            if(slow==fast)return true;
        }
        return false;
    }
}

5.环形链表 II 题目链接

  • 题目要求:给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
    如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
    不允许修改 链表。
    在这里插入图片描述
  • 代码及思路
    • 本题是在找链表是否为环的基础上找出环的入口点
    • 在找环的过程中,当快慢指针相遇时慢指针从头开始,然后快指针和慢指针每次相同速度移动,下一次相遇的节点即为环入口(具体分析需要数学)
    • 代码
/**
 * 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) {
        ListNode slow=head;
        ListNode fast=head;
        while(fast!=null&&fast.next!=null){
            slow=slow.next;
            fast=fast.next.next;
            if(slow==fast){
                slow=head;
                while(slow!=null){
                    if(slow==fast)return slow;
                    slow=slow.next;
                    fast=fast.next;
                }
            }
        }
        return null;
    }
}

6. 合并 K 个升序链表 题目链接

  • 题目要求:给你一个链表数组,每个链表都已经按升序排列。
    请你将所有链表合并到一个升序链表中,返回合并后的链表。
    在这里插入图片描述
  • 代码及思路
    • 采用逐个合并的方法,每次合并当前链表前已经合并的链表和当前链表
    • 代码
class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if(lists.length==0)return null;
        if(lists.length==1)return lists[0];
        ListNode newHead=new ListNode();
        newHead.next=mergeTwo(lists[0],lists[1]);
        for(int i=2;i<lists.length;i++){
            newHead.next=mergeTwo(newHead.next,lists[i]);
        }
        return newHead.next;
    }
    private ListNode mergeTwo(ListNode l1,ListNode l2){
        ListNode dumpy=new ListNode();
        ListNode cur=dumpy;
        while(l1!=null&&l2!=null){
            if(l1.val<=l2.val){
                cur.next=l1;
                l1=l1.next;
            }else{
                cur.next=l2;
                l2=l2.next;
            }
            cur=cur.next;
        }
        cur.next=l1!=null?l1:l2;
        return dumpy.next;
    }
}

7.相交链表 题目链接

  • 题目要求:给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。
    图示两个链表在节点 c1 开始相交:
    在这里插入图片描述
  • 代码及思路
    • 计算两个链表的长度,让较长的链表先走 (lengthA - lengthB) 步,这样两个链表就从同一节点开始遍历
    • 然后同时遍历两个链表,找到第一个相同的节点,即为相交节点
    • 代码
/**
 * 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) {
        ListNode curA=headA;
        ListNode curB=headB;
        int l1=0;
        int l2=0;
        while(curA!=null){
            l1++;
            curA=curA.next;
        }
        while(curB!=null){
            l2++;
            curB=curB.next;
        }
        int move=Math.abs(l1-l2);
        curA=l1>l2?headA:headB;
        curB=l1>l2?headB:headA;
        while(move-->0){
            curA=curA.next;
        }
        while(curA!=null&&curB!=null){
            if(curA==curB)return curA;
            curA=curA.next;
            curB=curB.next;
        }
        return null;
    }
}

8. 删除链表的倒数第 N 个结点 题目链接

  • 给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
    在这里插入图片描述
  • 代码及思路
    • 使用快慢指针,快指针先移动n次
    • 然后快慢指针以相同速度每次移动一个节点一起移动,当快指针到达最后一个节点时,慢指针的next指向要被删除的节点,删除即可
    • 为了统一处理,使用一个虚拟节点
    • 代码
/**
 * 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) {
        ListNode dumpy=new ListNode();
        dumpy.next=head;
        ListNode slow=dumpy;
        ListNode fast=dumpy;
        while(n-->0){
            fast=fast.next;
        }
        while(fast.next!=null){
            slow=slow.next;
            fast=fast.next;
        }
        slow.next=slow.next.next;
        return dumpy.next;
    }
}

9. 排序链表 题目链接

  • 题目要求:给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。
    在这里插入图片描述
  • 代码及思路
    • 使用快排的思想,每次每次找到链表的中间节点,然后将链表分成两个子链表进行排序
    • 然后将两个排序后的子链表合并成一个链表(之前已经做过)
    • 代码
class Solution {
    public ListNode sortList(ListNode head) {
        if(head==null||head.next==null)return head;
        ListNode mid=findMid(head);
        ListNode rightHead=mid.next;
        mid.next=null;
        ListNode n1=sortList(head);
        ListNode n2=sortList(rightHead);
        return mergr(n1,n2);
    }
    private ListNode findMid(ListNode head){
        if(head==null||head.next==null){
            return head;
        }
        ListNode slow=head;
        ListNode fast=head.next.next;
        while(fast!=null&&fast.next!=null){
            slow=slow.next;
            fast=fast.next.next;
        }
        return slow;
    }
    private ListNode mergr(ListNode n1,ListNode n2){
        ListNode dumpy=new ListNode();
        ListNode cur=dumpy;
        while(n1!=null&&n2!=null){
            if(n1.val<=n2.val){
                cur.next=n1;
                n1=n1.next;
            }else{
                cur.next=n2;
                n2=n2.next;
            }
            cur=cur.next;
        }
        cur.next=n1!=null?n1:n2;
        return dumpy.next;
    }
}

10. 两数相加 题目链接

  • 题目要求:给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
    请你将两个数相加,并以相同形式返回一个表示和的链表。
    你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
    在这里插入图片描述
  • 代码及思路
    • 遍历两个链表,每一次分别使用两个整数取出两个链表中节点值
    • 如果链表节点为空,则该整数值为0即可
    • 每次相加之后注意需要进位,因此当前结果值应该是两个链表节点值和上一节点和的进位之和与10取余
    • 最后注意两个链表都为空后还要看最后有没有进位
    • 代码
class Solution {
    public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
        int c=0;
        ListNode dumpy=new ListNode();
        ListNode cur=dumpy;
        while(l1!=null||l2!=null){
            int a=0;
            int b=0;
            if(l1!=null){
                a=l1.val;
                l1=l1.next;
            }
            if(l2!=null){
                b=l2.val;
                l2=l2.next;
            }
            int num=(a+b+c)%10;
            c=(a+b+c)/10;
            ListNode node=new ListNode(num);
            cur.next=node;
            cur=cur.next;
        }
        if(c!=0){
            cur.next=new ListNode(c);
        }
        return dumpy.next;
    }
}

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

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

相关文章

Spring MVC域对象共享数据

在Spring MVC中&#xff0c;域对象&#xff08;Domain Object&#xff09;通常指的是与业务逻辑相关的模型对象&#xff0c;它们代表了应用程序中的核心数据结构。例如&#xff0c;在一个电商应用中&#xff0c;Product、User、Order等类可以被视为域对象。这些对象通常与数据库…

Pod基础使用

POD基本操作 1.Pod生命周期 在Kubernetes中&#xff0c;Pod的生命周期经历了几个重要的阶段。下面是Pod生命周期的详细介绍&#xff1a; Pending&#xff08;待处理&#xff09;: 调度: Pod被创建后&#xff0c;首先进入“Pending”状态。此时&#xff0c;Kubernetes的调度器…

设计模式24-命令模式

设计模式24-命令模式 写在前面行为变化模式 命令模式的动机定义与结构定义结构 C 代码推导优缺点应用场景总结补充函数对象&#xff08;Functors&#xff09;定义具体例子示例&#xff1a;使用函数对象进行自定义排序代码说明输出结果具体应用 优缺点应用场景 命令模式&#xf…

查看 CUDA 和 cuDNN 版本

在安装 onnxruntime-gpu 选择版本时需要查看本机 CUDA 和 cuDNN 版本。 查看 CUDA 和 cuDNN 版本 import platform import torchprint("python.version:", platform.python_version()) print("torch.version:", torch.__version__) print("CUDA.vers…

汽车管理 API 接口:开启高效车辆运营新时代

API&#xff08;Application Programming Interface&#xff09;是一种接口&#xff0c;用于不同软件之间的通信。在汽车管理领域&#xff0c;API的应用可以帮助提升车辆运营的效率&#xff0c;让车主和车辆管理者更方便地获取车辆相关信息&#xff0c;进行保养和维修等工作。本…

fastadmin api中无法获取用户信息

控制器使用_initialize方法时&#xff0c;要增加 parent::_initialize(); 这行代码&#xff0c;否则会出现获取不到用户信息的问题&#xff1a; public function _initialize() {// 你的逻辑内容// ...// endparent::_initialize(); }

Chapter 01 Vue入门

前言 Vue 是一个框架&#xff0c;也是一个生态&#xff0c;其功能覆盖了大部分前端开发常见的需求。本文详细讲解了 Vue 的基本概念以及 Vue 开发者工具的安装。 一、Vue简介 ①定义 Vue 是一款用于构建用户界面的渐进式框架。它基于标准 HTML、CSS 和 JavaScript 构建&…

基于RDMA技术的Mayastor解决方案

1. 方案背景和挑战 1.1. Mayastor简介 OpenEBS是一个广受欢迎的开源云原生存储解决方案&#xff0c;托管于CNCF&#xff08;云原生计算基金会&#xff09;之下&#xff0c;旨在通过扩展Kubernetes的能力&#xff0c;为有状态应用提供灵活的持久性存储。Mayastor是OpenEBS项目…

maxscale

入门 官网&#xff1a;https://mariadb.com/kb/en/maxscale/ 开发语言&#xff1a;C 是否支持分片&#xff1a;不支持 支持的数据库&#xff1a;MySQL/Mariadb 路由规则&#xff1a;事务包裹的SQL会全部走写库、没有事务包裹SQL读写库通过设置Hint实现。其它功能通过配置文件实…

微服务通信

1、Feign远程调用 Feign是Spring Cloud提供的⼀个声明式的伪Http客户端&#xff0c; 它使得调⽤远程服务就像调⽤本地服务⼀样简单&#xff0c; 只需要创建⼀个接⼝并添加⼀个注解即可。 Nacos很好的兼容了Feign&#xff0c; Feign 默认集为Ribbon&#xff0c; 所以在Nacos下使…

M8020A J-BERT 高性能比特误码率测试仪

M8020A 比特误码率测试仪 J-BERT M8020A 高性能 BERT 产品综述 Keysight J-BERT M8020A 高性能比特误码率测试仪能够快速、准确地表征传输速率高达 16 或 32 Gb/s 的单通道和多通道器件中的接收机。 M8020A 综合了更广泛的功能&#xff0c;可以简化您的测试系统。 自动对信…

AGV导航方法大盘点:3大类,12小类

导语 大家好&#xff0c;我是社长&#xff0c;老K。专注分享智能制造和智能仓储物流等内容。 在自动化物流领域&#xff0c;自动导引车&#xff08;AGV&#xff09;扮演着至关重要的角色。它们不仅能够提高搬运效率&#xff0c;还能在各种环境中准确无误地完成任务。 而这一切的…

KVM虚拟化之命令行界面创建KVM虚拟机

环境&#xff1a;CentOS8 安装所需软件包 yum groupinstall -y "Virtualization*" 上传一个ISO镜像 使用指令创建KVM虚拟机 给KVM虚拟机创建一个磁盘 -f:指定磁盘类型为qcow2 使用指令创建一个虚拟机 virt-install \ --nameCentos-2 \ --vcpu 1 \ --memory 2048 \ -…

【SpringCloud】(一文通)服务注册/服务发现-Eureka

目 录 一. 背景1.1 问题描述1.2 解决思路1.3 什么是注册中心1.4 CAP理论1.5 常见的注册中心 二. Eureka 介绍三. 搭建Eureka Server3.1 创建 Eureka-server 子模块3.2 引入 eureka-server 依赖3.3 项目构建插件3.4 完善启动类3.5 编写配置文件3.6 启动服务 四. 服务注册4.1 引入…

Docker基础概述、Docker安装、Docker镜像加速、Docker镜像指令

1.为什么学docker 开发环境与测试环境不同&#xff0c;导致错误 因此docker提供解决方法———系统平滑移植&#xff0c;容器虚拟化技术 将代码与软件与配置文件 打包成一个镜像 2.docker的历练 创建一个开发环境内成为镜像文件再用docker使用镜像 3.什么是docker Docke…

泛型篇(Java - 泛型机制)(持续更新迭代)

目录 私聊 一、什么是泛型&#xff0c;泛型有什么用&#xff0c;为什么要用 1. 说法一 1.1 什么是泛型 1.2 泛型的使用 1.3 为什么要用泛型 2. 说法二 2.1 什么是泛型&#xff0c;泛型有什么用&#xff0c;为什么要用 2.2 怎么使用泛型&#xff0c;泛型可以作用在什么…

私有方法加事务注解会导致事务失效

这里idea其实已经提醒了使用事务不能用私有方法&#xff0c;这其实是个常见问题&#xff0c;这里主要就加深印象

XSS复现

目录 XSS简单介绍 一、反射型 1、漏洞逻辑&#xff1a; 为什么有些标签可以触发&#xff0c;有些标签不能触发 可以触发的标签 不能触发的标签 为什么某些标签能触发而某些不能 二、DOM型 1、Ma Spaghet! 要求&#xff1a; 分析&#xff1a; 结果&#xff1a; 2、J…

计算xpclr

1.conda安装xpclr 首先安装流程很轻松 conda create -n xpclr -c bioconda xpclr conda activate xpclr xpclr -h 2.按照要求准备文件 XPCLR - 简书 (jianshu.com) 根据教程准备文件&#xff0c;vcf&#xff0c;计算好的map&#xff0c;以及样本文件txt 其实官网也有介绍…

django学习入门系列之第九点《案例 Flask+MySQL新增用户》

文章目录 1 新增用户往期回顾 1 新增用户 from flask import Flask, render_template, request import pymysqlapp Flask(__name__)# 创建了网址 /nima和函数index的对应关系 # 以后用户在浏览器上访问/nima自动运行函数 app.route("/nima", methods[GET, POST]) d…