【leetcode题解】链表

news2025/3/26 5:52:59

目录

 链表

两数相加

两两交换链表中的节点

重排链表

合并 K 个升序链表(困难)

K 个一组翻转链表


 链表

1. 常用技巧

  1. 画图!!!(直观+形象,便于我们理解)
  2. 引入虚拟“头”节点(便于处理边界情况;方便我们对链表进行操作)
  3. 不要吝啬空间,大胆去定义变量
  4. 快慢双指针(判环;找链表中环的入口;找链表中倒数第n个节点)

2. 链表中的常用操作

  1. 创建一个新节点 new
  2. 尾插
  3. 头插(逆序链表)
两数相加

2. 两数相加 - 力扣(LeetCode)

/**
 * 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 addTwoNumbers(ListNode l1, ListNode l2) {
        ListNode cur1 = l1, cur2 = l2;
        ListNode newHead = new ListNode(0);// 创建一个虚拟头节点,方便记录结果
        ListNode prev = newHead;// 尾插操作的尾指针
        int t = 0;// 记录进位
        while (cur1 != null || cur2 != null || t != 0) {
            // 先加上第一个链表
            if (cur1 != null) {
                t += cur1.val;
                cur1 = cur1.next;
            }
            // 再加上第二个链表
            if (cur2 != null) {
                t += cur2.val;
                cur2 = cur2.next;
            }
            prev.next = new ListNode(t % 10);
            prev = prev.next;
            t /= 10;
        }
        return newHead.next;//
    }
}
两两交换链表中的节点

24. 两两交换链表中的节点 - 力扣(LeetCode)

解法一:递归

解法二:循环、迭代(模拟)

/**
 * 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 newhead = new ListNode(0);// 虚拟“头”节点
        newhead.next = head;
        ListNode prev = newhead, cur = prev.next, next = cur.next, nnext = next.next;
        while (cur != null && next != null) {
            // 1. 交换节点
            prev.next = next;
            next.next = cur;
            cur.next = nnext;
            // 2. 修改指针
            prev = cur;// 注意顺序
            cur = nnext;
            if (cur != null)
                next = cur.next;
            if (next != null)
                nnext = next.next;
        }
        return newhead.next;
    }
}
重排链表

143. 重排链表 - 力扣(LeetCode)

解法:模拟

1. 找到链表的中间节点(快慢双指针)

2. 把后面的部分逆序(反转链表:双指针;头插法)

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 void reorderList(ListNode head) {
        // 处理边界情况
        if (head == null || head.next == null || head.next.next == null)
            return;
        // 找链表的中间节点
        ListNode fast = head, slow = head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        // 此时,slow指向中间节点
        // 2. 把slow后面的部分逆序 - 头插法
        ListNode newhead = new ListNode(0);// 虚拟头节点
        ListNode cur = slow.next;//
        ListNode prev = null;
        slow.next = null;// 把两个链表分离
        while (cur != null) {
            ListNode next = cur.next;// 保存下一个节点
            cur.next = newhead.next;
            newhead.next = cur;
            cur = next;
        }
        // 3. 合并两个链表 - 双指针
        ListNode cur1 = head, cur2 = newhead.next;
        ListNode ret = new ListNode(0);
        prev = ret;
        while (cur1 != null) {
            // 先放第一个链表
            prev.next = cur1;
            prev = cur1;
            cur1 = cur1.next;
            // 合并第二个链表
            if (cur2 != null) {
                prev.next = cur2;
                prev = cur2;
                cur2 = cur2.next;
            }
        }

    }
}
合并 K 个升序链表(困难)

23. 合并 K 个升序链表 - 力扣(LeetCode)

解法一:暴力解法(不推荐)

解法二:利用优先级队列做优化

/**
 * 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 mergeKLists(ListNode[] lists) {
        // 创建一个小根堆
        PriorityQueue<ListNode> heap = new PriorityQueue<>((v1, v2) -> v1.val - v2.val);
        // 把所有的头节点放进小根堆
        for (ListNode head : lists) {
            if (head != null)
                heap.offer(head);
        }
        // 合并链表
        ListNode ret = new ListNode(0);
        ListNode prev = ret;
        while (!heap.isEmpty()) {
            ListNode t = heap.poll();
            prev.next = t;
            prev = t;
            if (t.next != null)
                heap.offer(t.next);
        }
        return ret.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 mergeKLists(ListNode[] lists) {
        return merge(lists, 0, lists.length - 1);
    }

    public ListNode merge(ListNode[] lists, int left, int right) {
        if (left > right)
            return null;
        if (left == right)
            return lists[left];
        // 平分数组
        int mid = (left + right) / 2;
        // [left,mid] [mid+1,right]
        // 处理左右两部分
        ListNode l1 = merge(lists, left, mid);
        ListNode l2 = merge(lists, mid + 1, right);
        return mergeTwo(l1, l2);
    }

    public ListNode mergeTwo(ListNode l1, ListNode l2) {
        // 合并两个链表
        if (l1 == null)
            return l2;
        if (l2 == null)
            return l1;
        ListNode head = new ListNode(0);
        ListNode cur1 = l1, cur2 = l2, prev = head;
        while (cur1 != null && cur2 != null) {
            if (cur1.val < cur2.val) {//
                prev.next = cur1;
                prev = cur1;
                cur1 = cur1.next;
            } else {
                prev.next = cur2;
                prev = cur2;
                cur2 = cur2.next;
            }
        }
        if (cur1 != null)
            prev.next = cur1;
        if (cur2 != null)
            prev.next = cur2;
        return head.next;
    }
}
K 个一组翻转链表

25. K 个一组翻转链表 - 力扣(LeetCode)

解法:模拟

  1. 先求出需要逆序多少组:n
  2. 重复n次,长度为k的链表的逆序即可(头插法)
/**
 * 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 reverseKGroup(ListNode head, int k) {
        // 1. 先求出需要逆序多少组
        int n = 0;
        ListNode cur = head;
        while (cur != null) {
            cur = cur.next;
            n++;
        }
        n /= k;
        // 2. 重复n次:长度为k的链表的逆序
        ListNode newhead = new ListNode(0);
        ListNode prev = newhead;
        cur = head;
        for (int i = 0; i < n; i++) {
            ListNode tmp = cur;
            for (int j = 0; j < k; j++) {
                // 头插
                ListNode next = cur.next;
                cur.next = prev.next;
                prev.next = cur;
                cur = next;
            }
            prev = tmp;
        }
        // 把后面不需要逆序的部分连接上
        prev.next = cur;
        return newhead.next;
    }
}

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

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

相关文章

Windows打开ftp局域网共享

前提是windows已经设置好开机账号密码了&#xff0c;否则教程不适用 第一先打开电脑ftp共享配置 点击保存即可 2.设置要共享到其他电脑的文件路径&#xff08;如果你要共享整个盘你就设置整个盘&#xff0c;如果是共享盘中某文件就设置某文件&#xff0c;这里是某文件&#x…

我爱学算法之——滑动窗口攻克子数组和子串难题(中)

学习算法&#xff0c;继续加油&#xff01;&#xff01;&#xff01; 一、将 x 减到 0 的最小操作数 题目解析 来看这一道题&#xff0c;题目给定一个数组nums和一个整数x&#xff1b;我们可以在数组nums的左边或者右边进行操作&#xff08;x减去该位置的值&#xff09;&#…

从零开始上手huggingface

1. 环境配置 # git 安装&#xff1a;https://git-scm.com/ # git lfs安装&#xff1a;https://git-lfs.com git lfs install # huggingface-cli 安装&#xff1a;https://huggingface.co/docs/hub/index pip install huggingface_hub2. 网站直接下载模型 可能会中断&#xff…

用 pytorch 从零开始创建大语言模型(六):对分类进行微调

用 pytorch 从零开始创建大语言模型&#xff08;六&#xff09;&#xff1a;对分类进行微调 6 微调用于分类6.1 微调的不同类别6.2 准备数据集6.3 创建数据加载器6.4 使用预训练权重初始化模型6.5 添加分类头部6.6 计算分类损失和准确率6.7 在监督数据上微调模型6.8 使用LLM进…

Netty——BIO、NIO 与 Netty

文章目录 1. 介绍1.1 BIO1.1.1 概念1.1.2 工作原理1.1.3 优缺点 1.2 NIO1.2.1 概念1.2.2 工作原理1.2.3 优缺点 1.3 Netty1.3.1 概念1.3.2 工作原理1.3.3 优点 2. Netty 与 Java NIO 的区别2.1 抽象层次2.2 API 易用性2.3 性能优化2.4 功能扩展性2.5 线程模型2.6 适用场景 3. 总…

【Linux】信号:信号保存和处理

&#x1f525;个人主页&#xff1a;Quitecoder &#x1f525;专栏&#xff1a;linux笔记仓 目录 01.阻塞信号信号集 02.捕捉信号sigaction可重入函数volatileSIGCHLD 01.阻塞信号 实际执行信号的处理动作称为信号递达&#xff1a;每个信号都有一个默认行为&#xff0c;例如终…

应用权限组列表

文章目录 使用须知位置相机麦克风通讯录日历运动数据身体传感器图片和视频音乐和音频跨应用关联设备发现和连接剪切板文件夹文件(deprecated) 使用须知 在申请目标权限前&#xff0c;建议开发者先阅读应用权限管控概述-权限组和子权限&#xff0c;了解相关概念&#xff0c;再合…

MATLAB实现基于“蚁群算法”的AMR路径规划

目录 1 问题描述 2 算法理论 3 求解步骤 4 运行结果 5 代码部分 1 问题描述 移动机器人路径规划是机器人学的一个重要研究领域。它要求机器人依据某个或某些优化原则 (如最小能量消耗&#xff0c;最短行走路线&#xff0c;最短行走时间等)&#xff0c;在其工作空间中找到一…

【深度学习】多目标融合算法(五):定制门控网络CGC(Customized Gate Control)

目录 一、引言 二、CGC&#xff08;Customized Gate Control&#xff0c;定制门控网络&#xff09; 2.1 技术原理 2.2 技术优缺点 2.3 业务代码实践 2.3.1 业务场景与建模 2.3.2 模型代码实现 2.3.3 模型训练与推理测试 2.3.4 打印模型结构 三、总结 一、引言 上一…

【NLP 42、实践 ⑪ 用Bert模型结构实现自回归语言模型的训练】

如果结局早已注定&#xff0c;那么过程就将大于结局 —— 25.3.18 自回归语言模型&#xff1a;由前文预测后文的语言模型 特点&#xff1a;单向 训练方式&#xff1a;利用前n个字预测第n1个字&#xff0c;实现一个mask矩阵&#xff0c;送入Bert模型&#xff0c;让其前文看不到…

TCP | 序列号和确认号 [逐包分析] | seq / ack 详解

注 &#xff1a; 本文为 “TCP 序号&#xff08;seq&#xff09;与确认序号&#xff08;ack&#xff09;” 相关文章合辑。 英文引文&#xff0c;机翻未校。 中文引文&#xff0c;略作重排。 如有内容异常&#xff0c;请看原文。 Understanding TCP Seq & Ack Numbers […

在Linux、Windows系统上安装开源InfluxDB——InfluxDB OSS v2并设置开机自启的保姆级图文教程

一、进入InfluxDB下载官网 InfluxData 文档https://docs.influxdata.com/Install InfluxDB OSS v2 | InfluxDB OSS v2 Documentation

考研复习之队列

循环队列 队列为满的条件 队列为满的条件需要特殊处理&#xff0c;因为当队列满时&#xff0c;队尾指针的下一个位置应该是队头指针。但是&#xff0c;我们不能直接比较 rear 1 和 front 是否相等&#xff0c;因为 rear 1 可能会超出数组索引的范围。因此&#xff0c;我们需…

智慧高速,安全护航:视频监控平台助力高速公路高效运营

随着我国高速公路里程的不断增长&#xff0c;交通安全和运营效率面临着前所未有的挑战。传统的监控方式已难以满足现代化高速公路管理的需求&#xff0c;而监控视频平台的出现&#xff0c;则为高速公路的安全运营提供了强有力的技术支撑。高速公路视频监控联网解决方案 高速公路…

Jboss漏洞再现

一、CVE-2015-7501 1、开环境 2、访问地址 / invoker/JMXInvokerServlet 出现了让下载的页面&#xff0c;说明有漏洞 3、下载ysoserial工具进行漏洞利用 4、在cmd运行 看到可以成功运行&#xff0c;接下来去base64编码我们反弹shell的命令 5、执行命令 java -jar ysoserial-…

【Linux系统】Linux权限讲解!!!超详细!!!

目录 Linux文件类型 区分方法 文件类型 Linux用户 用户创建与删除 用户之间的转换 su指令 普通用户->超级用户(root) 超级用户(root) ->普通用户 普通账户->普通账户 普通用户的权限提高 sudo指令 注&#xff1a; Linux权限 定义 权限操作 1、修改文…

2.创建Collection、添加索引、加载内存、预览和搜索数据

milvus官方文档 milvus2.3.1的官方文档地址: https://milvus.io/docs/v2.3.x 使用attu创建collection collection必须要有一个主键字段、向量字段 确保字段类型与索引类型兼容 字符串类型&#xff08;VARCHAR&#xff09;通常需要使用 Trie 索引&#xff0c;而不是 AutoInd…

AIGC 新势力:探秘海螺 AI 与蓝耘 MaaS 平台的协同创新之旅

探秘海螺AI&#xff1a;多模态架构下的认知智能新引擎 在人工智能持续进阶的进程中&#xff0c;海螺AI作为一款前沿的多功能AI工具&#xff0c;正凭借其独特的多模态架构崭露头角。它由上海稀宇科技有限公司&#xff08;MiniMax&#xff09;精心打造&#xff0c;依托自研的万亿…

一文解读DeepSeek在法律商业仲裁细分行业的应用

引言 当AI闯入法律界&#xff1a;DeepSeek如何把商业仲裁变成“纠纷快车道” AI技术正在像水电煤一样渗透生活&#xff0c;随着DeepSeek的爆火出圈&#xff0c;全国各行各业都在如火如荼地接入DeepSeek&#xff0c;以期望利用DeepSeek的“超能力”来重塑各自行业的效能和格局&a…

快速入手-基于Django的主子表间操作mysql(五)

1、如果该表中存在外键&#xff0c;结合实际业务情况&#xff0c;那可以这么写&#xff1a; 2、针对特殊的字典类型&#xff0c;可以这么定义 3、获取元组中的字典值和子表中的value值方法 4、对应的前端页面写法