当前位置: 首页 > news >正文

LeetCode 92. 反转链表 II - 算法解析

文章目录

  • LeetCode 92. 反转链表 II - 算法解析
    • 问题描述
    • 代码实现
    • 算法思路
      • 1. 边界处理和初始化
      • 2. 找到反转区间的前一个节点
      • 3. 反转指定区间的链表
      • 4. 重新连接链表
    • 图解示例
      • 初始状态
      • 找到preLeft
      • 反转过程
      • 重新连接
      • 最终结果
    • 复杂度分析

LeetCode 92. 反转链表 II - 算法解析

问题描述

给你单链表的头指针 head 和两个整数 left 和 right,其中 left <= right。请你反转从位置 left 到位置 right 的链表节点,返回反转后的链表。

代码实现

class Solution {public ListNode reverseBetween(ListNode head, int left, int right) {if(head==null || head.next==null){return head;}ListNode dummy = new ListNode(0,head);ListNode preLeft = dummy;for (int i = 0; i < left - 1; i++) {preLeft=preLeft.next;}ListNode pre=null,cur=preLeft.next;for (int i = 0; i < right - left + 1; i++) {ListNode nxt = cur.next;cur.next= pre;pre=cur;cur=nxt;}preLeft.next.next=cur;preLeft.next=pre;return dummy.next;}
}

算法思路

这个算法采用原地反转的方式,分为以下几个关键步骤:

1. 边界处理和初始化

if(head==null || head.next==null){return head;
}
ListNode dummy = new ListNode(0,head);
  • 处理空链表或单节点链表的边界情况
  • 创建虚拟头节点dummy,简化边界处理(特别是当left=1时)

2. 找到反转区间的前一个节点

ListNode preLeft = dummy;
for (int i = 0; i < left - 1; i++) {preLeft=preLeft.next;
}
  • preLeft指向第left个节点的前一个节点
  • 这个节点很关键,因为反转后需要重新连接

3. 反转指定区间的链表

ListNode pre=null,cur=preLeft.next;
for (int i = 0; i < right - left + 1; i++) {ListNode nxt = cur.next;cur.next= pre;pre=cur;cur=nxt;
}

这是标准的链表反转操作:

  • pre: 前一个节点(初始为null)
  • cur: 当前节点(从第left个节点开始)
  • nxt: 下一个节点(临时保存)

反转过程

  1. 保存下一个节点:nxt = cur.next
  2. 反转当前节点的指针:cur.next = pre
  3. 移动指针:pre = cur, cur = nxt
  4. 重复right - left + 1

4. 重新连接链表

preLeft.next.next=cur;
preLeft.next=pre;
  • preLeft.next.next=cur: 将原来的第left个节点(现在是反转区间的尾节点)连接到反转区间后面的节点
  • preLeft.next=pre: 将preLeft连接到反转后的头节点

图解示例

head = [1,2,3,4,5], left = 2, right = 4为例:

初始状态

dummy -> 1 -> 2 -> 3 -> 4 -> 5 -> null^    ^         ^preLeft  |         |反转区间起点 反转区间终点

找到preLeft

dummy -> 1 -> 2 -> 3 -> 4 -> 5 -> null^preLeft

反转过程

第1次反转

pre=null, cur=2, nxt=3
2.next = null
pre=2, cur=3

第2次反转

pre=2, cur=3, nxt=4
3.next = 2
pre=3, cur=4

第3次反转

pre=3, cur=4, nxt=5
4.next = 3
pre=4, cur=5

重新连接

preLeft.next.next = cur  // 2.next = 5
preLeft.next = pre       // 1.next = 4

最终结果

dummy -> 1 -> 4 -> 3 -> 2 -> 5 -> null

返回[1,4,3,2,5]
在这里插入图片描述

复杂度分析

  • 时间复杂度:O(n)

    • 第一个循环:O(left) ≤ O(n)
    • 第二个循环:O(right - left + 1) ≤ O(n)
    • 总体:O(n)
  • 空间复杂度:O(1)

    • 只使用了常数个额外变量
    • 原地反转,没有使用额外的数据结构
http://www.dtcms.com/a/358949.html

相关文章:

  • 微服务-ruoyi-cloud部署
  • 《动手学深度学习v2》学习笔记 | 2.3 线性代数
  • 吴恩达机器学习(三)
  • 第7.5节:awk语言 switch 语句
  • 【C++】掌握string类操作:高效处理字符串
  • k230 按键拍照后,将摄像头拍照的1920*1080分辨率的图片以jpg文件格式,保存到板载TF存储卡的指定文件夹目录中
  • MinerU本地化部署
  • Java的Optional实现优雅判空新体验【最佳实践】
  • 做一个实用的节假日工具
  • MQTT 连接建立与断开流程详解(一)
  • sunset: decoy靶场渗透
  • 20250830_Oracle 19c CDB+PDB(QMS)默认表空间、临时表空间、归档日志、闪回恢复区巡检手册
  • day42-Ansible
  • 动态规划--Day05--最大子数组和--53. 最大子数组和,2606. 找到最大开销的子字符串,1749. 任意子数组和的绝对值的最大值
  • 微信小程序开发教程(三)
  • java如何保证线程安全
  • RLPD——利用离线数据实现高效的在线RL:不进行离线RL预训练,直接应用离策略方法SAC,在线学习时对称采样离线数据
  • 【OpenGL】LearnOpenGL学习笔记17 - Cubemap、Skybox、环境映射(反射、折射)
  • 【pandas】.loc常用操作
  • 【SpringMVC】SSM框架【二】——SpringMVC超详细
  • 【运维篇第三弹】《万字带图详解分库分表》从概念到Mycat中间件使用再到Mycat分片规则,详解分库分表,有使用案例
  • DAEDAL:动态调整生成长度,让大语言模型推理效率提升30%的新方法
  • 基于SpringBoot的电脑商城系统【2026最新】
  • 漫谈《数字图像处理》之分水岭分割
  • SystemVerilog学习【七】包(Package)详解
  • REST-assured获取响应数据详解
  • 数据结构 | 深度解析二叉树的基本原理
  • 访问Nginx 前端页面,接口报502 Bad Gateway
  • 【DeepSeek】ubuntu安装deepseek、docker、ragflow
  • 简历书写---自我评价怎么写