LeetCode 25 - K 个一组翻转链表

LeetCode 25 - K 个一组翻转链表

这道题是一个典型的链表操作题,考察我们对链表的精确操作,包括反转链表、分组处理、递归和迭代的结合应用等。还可以通过变体问题延伸到优先队列操作、归并、分块等,这使得它成为面试中的高频考题之一。


题目描述

给你一个链表,每 k 个节点一组进行翻转,并返回翻转后的链表。

  • k 是一个正整数,它的值小于或等于链表的长度。
  • 如果节点总数不是 k 的整数倍,那么请将最后剩余节点保持原样。
  • 你不允许更改节点的值,只能调整节点指针的方向。

示例

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

解题思路与分析

核心简化问题

  1. 分段处理链表:将链表分成每 k 个一组。
  2. 对每一组执行反转操作。
  3. 当遍历到不足 k 个节点的部分时,维持原顺序不再反转。
  4. 方法可以通过递归或迭代完成。

解法与代码模板

解法 1:递归法

核心思路
  • 使用递归配合局部反转:
    1. 确定链表是否有足够的 k 个节点:如果不足 k 个,直接返回头节点。
    2. 如果有足够的 k 个节点:
      • 完成当前组内 k 个节点的反转,
      • 递归地对剩余部分链表继续处理。
    3. 将当前反转的部分连接到下一组递归结果。
模板代码
class Solution {public ListNode reverseKGroup(ListNode head, int k) {// 检查链表是否有足够的 k 个节点ListNode current = head;int count = 0;while (current != null && count < k) {current = current.next;count++;}// 如果不足 k 个节点,直接返回原链表if (count < k) {return head;}// 反转当前 k 个节点ListNode prev = null, next = null;current = head;for (int i = 0; i < k; i++) {next = current.next;   // 暂存下一节点current.next = prev;  // 改变指针方向prev = current;       // 移动 prev 指针current = next;       // 移动 current 指针}// 递归处理剩余链表,并连接反转后的部分head.next = reverseKGroup(current, k);// 返回反转后的头节点return prev;}
}
复杂度分析
  • 时间复杂度: O(N)
    • 每个节点仅访问一次。
  • 空间复杂度: O(N / k)
    • 递归调用栈的深度为 (链表长度 / k)
优缺点
  • 优点:代码简洁并且逻辑清晰,适合递归思路的场景。
  • 缺点:会造成大量递归栈调用,链表很长时可能出现栈溢出。

解法 2:迭代法

核心思路
  • 相对于递归法,用 迭代 来实现分组反转链表,避免了递归栈空间的开销:
    1. 使用 哑结点dummy node)作为新链表的起始位置,方便连接。
    2. 遍历链表,分别找到每一组的起始结点和结束结点。
    3. 将当前分组进行反转,并连接到已经处理好的链表部分。
    4. 当剩余节点不足时,停止反转,直接连接到尾部。
模板代码
class Solution {public ListNode reverseKGroup(ListNode head, int k) {// 创建哑结点ListNode dummy = new ListNode(-1);dummy.next = head;ListNode prevGroupEnd = dummy;while (true) {// 找到当前组的开始和结束节点ListNode groupStart = prevGroupEnd.next;ListNode groupEnd = prevGroupEnd;for (int i = 0; i < k; i++) {groupEnd = groupEnd.next;if (groupEnd == null) {return dummy.next; // 不足 k 个节点}}// 下一组的起始节点ListNode nextGroupStart = groupEnd.next;// 反转当前组reverseList(groupStart, groupEnd);// 连接反转后的部分prevGroupEnd.next = groupEnd; // 当前组的结尾变成起始点groupStart.next = nextGroupStart;// 更新 prevGroupEnd 为这一组的最后节点prevGroupEnd = groupStart;}}private void reverseList(ListNode start, ListNode end) {ListNode prev = null, current = start, next = null;ListNode stop = end.next; // 保存停止位置while (current != stop) {next = current.next;current.next = prev;prev = current;current = next;}}
}
复杂度分析
  • 时间复杂度: O(N)
    • 每个节点最多被访问两次(反转和连接)。
  • 空间复杂度: O(1)
    • 没有额外栈空间的使用,仅需常数级别指针。
优缺点
  • 优点: 比递归方法更高效,适用于超长链表。
  • 缺点: 实现逻辑上稍微复杂。

解法 3:栈辅助法

核心思路
  • 借助栈来反转每一组节点:
    1. 遍历链表,将 k 个节点压入栈中。
    2. 当栈中节点数量达到 k 时,出栈并重新连接节点指针。
    3. 如果节点数量不足 k,直接连接剩余部分。
模板代码
import java.util.Stack;class Solution {public ListNode reverseKGroup(ListNode head, int k) {if (head == null || k <= 1) return head;Stack<ListNode> stack = new Stack<>();ListNode dummy = new ListNode(-1);ListNode prev = dummy;dummy.next = head;while (head != null) {// 将 k 个节点压入栈for (int i = 0; i < k && head != null; i++) {stack.push(head);head = head.next;}// 判断栈中是否有足够的 k 个节点if (stack.size() == k) {// 出栈并重新连接while (!stack.isEmpty()) {prev.next = stack.pop();prev = prev.next;}prev.next = head; // 连接当前组与下一组}}return dummy.next;}
}
复杂度分析
  • 时间复杂度: O(N)
    • 每个节点入栈、出栈一次。
  • 空间复杂度: O(k)
    • 栈空间用于存储每组 k 个节点。
优点和缺点
  • 优点: 实现简单,不需要复杂链表反转逻辑。
  • 缺点: 额外使用栈空间,适用于较短链表。

经典变体问题

变体 1:反转链表 II

  • 反转链表的第 m 到第 n 个节点(LeetCode 92)。
  • 解法类似,利用迭代进行指定区域反转。

变体 2:K 个一组翻转链表,但跳过一些组

  • 例如:对链表分组,但只翻转奇数组或者仅反转偶数组。

变体 3:分组排序

  • 例如:对链表的每组节点排序而不是反转。

快速 AC 总结

  1. 递归与迭代优先掌握
    • 递归:逻辑清晰但容易出现栈溢出,适用于理论验证。
    • 迭代:高效且空间复杂度较低,是面试中优选方法。
  2. 哑节点技巧
    • 在处理链表操作时,借助哑节点可以避免很多冗余的头节点边界条件处理。
  3. 多练变体问题
    • 如部分反转、跳过反转的场景,可以轻松迁移基础模板。

通过对链表反转操作的熟悉,配合经典模板化实现,可以快速应对链表转化类问题,并高效解决工程中复杂数据结构操作场景。

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

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

相关文章

Leetcode 54: 螺旋矩阵

Leetcode 54: 螺旋矩阵 是一道经典的矩阵遍历模拟题目&#xff0c;要求我们以螺旋顺序遍历一个二维数组。这个问题在面试中非常经典&#xff0c;考察模拟、数组操作以及逻辑清晰度。掌握本题的高效解法可以迅速给面试官留下好印象。 适合面试的解法&#xff1a;边界法&#xff…

abseil-cpp:环境搭建

参考: https://abseil.io/docs/cpp/quickstart-cmake abseil-cpp.git/dd4c89b abseil-cpp.git/20240722.1 1. clone代码仓库、编译 git clone https://github.com/abseil/abseil-cpp.git /app/abseil-cpp/ #/app/abseil-cpp/.git/config git checkout 20240722.1git rev-pa…

Storm实时流式计算系统(全解)——下

storm编程案例-网站访问来源实时统计-需求 storm编程-网站访问来源实时统计-代码实现 根据以上条件可以只写一个类&#xff0c;我们只需要写2个方法和一个main&#xff08;&#xff09;&#xff0c;一个读取/发射&#xff08;spout&#xff09;。 一个拿到数据统计后发到redis…

什么是SYN洪范攻击?

文章目录 一、什么是SYN洪范攻击&#xff1f;二、SYN泛洪攻击原理2.1 TCP 三次握手过程2.2 SYN攻击过程 三、防御措施 一、什么是SYN洪范攻击&#xff1f; SYN洪泛攻击&#xff08;SYN Flood&#xff09;发生在OSI第四层&#xff0c;是一种基于‌TCP协议三次握手漏洞‌的DoS&a…

【嵌入式】MQTT

MQTT 文章目录 MQTT安装简介MQTT客户端代码 安装 安装Paho MQTT C库: sudo apt-get install libpaho-mqtt3-dev头文件包含&#xff1a; #include "MQTTClient.h"编译选项&#xff1a; gcc -o $ $^ -lpaho-mqtt3c简介 MQTT协议全称是&#xff08;Message Queuing…

ubuntu离线安装nvidia-container-runtime

参考文章 ubuntu系统docker20.4版本安装nvidia-container-runtime3.11.0-1版本(离线安装nvidia-docker) - jokerMM - 博客园 https://zhuanlan.zhihu.com/p/15194336245 一、软件地址 Index of /nvidia-docker/libnvidia-container/stable/ 从上述地地址——进入对应系统—…

用Python+Flask打造可视化武侠人物关系图生成器:从零到一的实战全记录

用PythonFlask打造可视化武侠人物关系图生成器&#xff1a;从零到一的实战全记录 一、缘起&#xff1a;一个程序小白的奇妙探索之旅 作为一个接触Python仅13天的编程萌新&#xff0c;我曾以为开发一个完整的应用是遥不可及的事情。但在DeepSeek的帮助下&#xff0c;我竟用短短…

RPA 职业前景:个人职场发展的 “新机遇”

1. RPA职业定义与范畴 1.1 RPA核心概念 机器人流程自动化&#xff08;RPA&#xff09;是一种通过软件机器人模拟人类操作&#xff0c;自动执行重复性、规则性任务的技术。RPA的核心在于其能够高效、准确地处理大量数据和流程&#xff0c;减少人工干预&#xff0c;从而提高工作…

Full GC 排查

在 Java 中&#xff0c;Full GC&#xff08;完全垃圾回收&#xff09;会对整个堆&#xff08;包括年轻代和老年代&#xff0c;甚至可能包括永久代/元空间&#xff09;进行垃圾回收&#xff0c;通常会导致较长的停顿&#xff08;STW&#xff0c;Stop-The-World&#xff09;。如果…

go语言中字符串嵌套

在Go语言中&#xff0c;字符串嵌套通常是指在字符串中包含另一个字符串。可以通过以下几种方式实现&#xff1a; 1. 使用双引号和转义字符 如果需要在字符串中嵌套双引号&#xff0c;可以使用转义字符 \ 来表示内部的双引号。例如&#xff1a; s : "He said, \"He…

Docker 学习(二)——基于Registry、Harbor搭建私有仓库

Docker仓库是集中存储和管理Docker镜像的平台&#xff0c;支持镜像的上传、下载、版本管理等功能。 一、Docker仓库分类 1.公有仓库 Docker Hub&#xff1a;官方默认公共仓库&#xff0c;提供超过10万镜像&#xff0c;支持用户上传和管理镜像。 第三方平台&#xff1a;如阿里…

js的简单介绍

一.javascript&#xff08;是什么&#xff09; 是一种运行在客户端(浏览器)的编程语言&#xff0c;实现人机交互效果 作用 网页特效&#xff08;监听客户的一些行为让网页做出对应的反馈&#xff09;表单验证(针对表格数据的合法性进行判断)数据交互(获取后台的数据&#xf…

k8s架构及服务详解

目录 1.1.容器是什么1.2.Namespace1.3.rootfs5.1.Service介绍5.1.1.Serice简介 5.1.1.1什么是Service5.1.1.2.Service的创建5.1.1.3.检测服务5.1.1.4.在运行的容器中远程执行命令 5.2.连接集群外部的服务 5.2.1.介绍服务endpoint5.2.2.手动配置服务的endpoint5.2.3.为外部服务…

01. HarmonyOS应用开发实践与技术解析

文章目录 前言项目概述HarmonyOS应用架构项目结构Ability生命周期 ArkTS语言特性装饰器状态管理 UI组件与布局基础组件响应式布局样式与主题 页面路由与参数传递页面跳转参数接收 数据绑定与循环渲染数据接口定义循环渲染 条件渲染组件生命周期最佳实践与性能优化组件复用响应式…

【虚拟机 IP 配置深度剖析】

虚拟机 IP 配置深度剖析 在虚拟机的使用过程中&#xff0c;IP 配置犹如搭建房屋的基石&#xff0c;是确保虚拟机与外部网络顺畅通信、与其他设备高效交互的关键所在。本文将以 CentOS 虚拟机为例&#xff0c;深入解读 IP 配置的奥秘。 一、认识网络模式 • NAT 模式&#xf…

【Python 数据结构 5.栈】

目录 一、栈的基本概念 1.栈的概念 2.入栈 入栈的步骤 3.出栈 出栈的步骤 4.获取栈顶元素 获取栈顶元素的步骤 二、 Python中的栈 顺序表实现 链表实现 三、栈的实战 1.LCR 123. 图书整理 I 思路与算法 2.LCR 027. 回文链表 思路与算法 3.1614. 括号的最大嵌套深度 思路与算法 …

Machine Learning 初探

前置知识 pandas 读取文件&#xff1a;read_csv查看信息 describe&#xff1a;查看整体信息&#xff0c;包括每列的平均值、最大最小值、标准差等head&#xff1a;输出头部几行数据columns&#xff1a;输出所有列名loc&#xff1a;查询数据&#xff0c;或是根据索引取对应的数…

2025年2月个人工作生活总结

本文为 2025年2月工作生活总结。 工作记录 AI浪潮 AI非常火&#xff0c;春节至今&#xff0c;到处充斥着大量和AI、DeepSeek有关的新闻。领导也一再强调要用AI&#xff0c;甚至纳入到新一年的考核里。再往上&#xff0c;大领导开会的新闻稿里也作出要求&#xff0c;不能停下脚…

SpringBoot @ConfigurationProperties 注解使用

ConfigurationProperties 用于将配置文件&#xff08;如 application.properties 或 application.yml&#xff09;中的属性批量绑定到一个 Java Bean 中。 1. 定义配置文件 在 application.properties 或 application.yml 中定义一组具有相同前缀的属性。 application.yml &a…

刚安装docker并启动docker服务: systemctl restart docker报错解决

root:/home/lzw# sudo systemctl restart docker Job for docker.service failed because the control process exited with error code. See "systemctl status docker.service" and "journalctl -xeu docker.service" for details. 1、问题描述 启动doc…