力扣hot100:相交链表与反转链表详细思路讲解(160,206)

问题描述

核心思路:双指针交替遍历

算法思想: 使用两个指针 papb 分别从链表A和链表B的头节点出发,同步向后遍历。当任一指针走到链表末尾时,将其重定位到另一链表的头节点继续遍历。若两链表相交,papb 最终会在相交节点相遇;若不相交,则最终会同时到达 null

数学原理: 设链表A独立部分长度为 a,链表B独立部分长度为 b,公共部分长度为 c

  • 指针 pa 的路径:a + (b - c) + c = a + b
  • 指针 pb 的路径:b + (a - c) + c = a + b 两指针走过的总长度均为 a + b,因此必然在相交节点(或 null)相遇。

代码实现

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {if(headA==null||headB==null){return null;}ListNode pa=headA;ListNode pb=headB;while(pa!=pb){if(pa==null){pa=headB;}else{pa=pa.next;}if(pb==null){pb=headA;}else{pb=pb.next;}}return pa;}

复杂度分析

  • 时间复杂度:O(m + n),其中 m 和 n 分别为链表长度。
  • 空间复杂度:O(1),仅使用两个指针。

关键点

  1. 循环终止条件pa == pb 时退出循环(包括两者均为 null 的情况)。
  2. 重定位时机:当指针走到当前链表末尾时,立即切换到另一链表的头部。
  3. 不相交处理:两指针最终同时为 null,返回 null 符合预期。
其他解法对比
方法二:计算长度差(同步遍历)

思路

  1. 遍历两链表,分别计算长度 lenA 和 lenB
  2. 长链表指针先走 |lenA - lenB| 步。
  3. 两指针同步遍历,相遇点即为相交节点。

代码

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {int lenA = getLength(headA), lenB = getLength(headB);ListNode pa = headA, pb = headB;// 长链表指针先走差值步if (lenA > lenB) {for (int i = 0; i < lenA - lenB; i++) pa = pa.nextB; i++) pa = pa.next;} else {for (int i = 0; i < lenB - lenA; i++) pb = pb.next;}// 同步遍历直至相遇while (pa != pb) {pa = pa.next;pb = pb.next;}return pa;
}private int getLength(ListNode head) {int lenLength(ListNode head) {int len = 0;while (head != null) {len++;head = head.next;}return len;
}

复杂度

  • 时间复杂度:O(m + n)(需两次遍历)。
  • 空间复杂度:O(1)。

适用场景: 当链表长度差异较大时,此方法可能略快于双指针交替法。

方法三:哈希集合(空间换时间)

思路: 1时间) 思路

  1. 遍历链表A,将所有节点存入 HashSet
  2. 遍历链表B,检查节点是否在集合中,第一个存在的节点即为交点。

代码

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {Set<ListNode> set = new HashSet<>();while (headA != null) {set.add(headA);headA = headA.next;}while (headB != null) {if (set.contains(headB)) return headB;headB = headB.next;}return null;
}

复杂度

  • 时间复杂度:O(m + n)。
  • 空间复杂度:O(m)(存储链表A的节点)。

适用场景: 对空间复杂度不敏感时,代码最简洁直观。

方法对比总结
方法时间复杂度空间复杂度特点
双指针交替遍历O(m + n)O(1)空间最优,代码简洁
计算长度差O(m + n)O(1)逻辑清晰,略多一次遍历
哈希集合O(m + n)O(m)思路直接,但需额外空间

推荐:双指针交替遍历法在空间和代码简洁性上表现最佳,是面试中的理想解法。

问题描述

核心解法:迭代双指针法

算法思想: 使用双指针 new_headtemp 动态反转链表:

  • new_head:指向已反转部分的头节点(初始为null)
  • temp:遍历原链表的当前节点 每次迭代将当前节点从原链表断开,插入到反转链表的头部,实现原地反转。

代码实现

public ListNode reverseList(ListNode head) {ListNode new_head = null;ListNode temp = head;while (temp != null) {ListNode next = temp.next;  // 保存后继节点temp.next = new_head;      // 当前节点指向反转链表头部new_head = temp;           // 更新反转链表头temp = next;               // 移动到下一个节点}return new_head;
}

图解过程

原始链表:1 → 2 → 3 → 4 → null
迭代过程:
第1轮:new_head=1→null, temp=2
第2轮:new_head=2→1→null, temp=3
第3轮:new_head=3→2→1→null, temp=4
第4轮:new_head=4→3→2→1→null, temp=null

复杂度分析

  • 时间复杂度:O(n),仅需一次遍历
  • 空间复杂度:O(1),仅使用常量空间

优势

  • 原地操作,不占用额外空间
  • 逻辑清晰,代码简洁
  • 适用于所有编程语言的链表实现
其他经典解法
方法二:递归法(分治思想)

算法思想

  1. 递归到链表尾部
  2. 回溯时反转节点指向
  3. 返回新的头节点
public ListNode reverseList(ListNode head) {if (head == null || head.next == null) {return head;}ListNode newHead = reverseList(head.next); // 递归到尾部head.next.next = head;    // 反转指针方向head.next = null;         // 断开原指针return newHead;
}

复杂度分析

  • 时间复杂度:O(n)
  • 空间复杂度:O(n)(递归栈空间)

适用场景

  • 链表长度适中(避免栈溢出)
  • 需要简洁的代码表达
  • 函数式编程环境
方法三:头插法(使用虚拟节点)

算法思想

  1. 创建虚拟头节点 dummy
  2. 遍历原链表,将每个节点插入到 dummy 之后
  3. 返回 dummy.next
public ListNode reverseList(ListNode head) {ListNode dummy = new ListNode(-1);ListNode cur = head;while (cur != null) {ListNode next = cur.next;   // 保存后继节点cur.next = dummy.next;       // 头插操作dummy.next = cur;            // 更新头节点cur = next;                  // 移动指针}return dummy.next;
}

复杂度分析

  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

优势

  • 统一处理头节点特殊情况
  • 逻辑更易理解
  • 支持链表的其他变形操作
方法对比总结
方法时间复杂度空间复杂度特点
迭代双指针O(n)O(1)空间最优,推荐首选
递归法O(n)O(n)代码简洁,但空间消耗大
头插法(虚拟节点)O(n)O(1)逻辑清晰,易扩展

核心技巧

  1. 指针保存:在修改节点指针前,必须保存后继节点引用
  2. 头插操作:将节点插入链表头部是反转的关键
  3. 终止条件:注意处理空链表和单节点链表的边界情况

延伸思考

  • 如何反转部分链表(区间反转)?
  • 如何K个一组反转链表?
  • 如何判断链表是否有环?(快慢指针技巧)

迭代双指针法因其优异的时空复杂度,成为面试和工程实践中的首选方案。掌握这三种经典解法,能够灵活应对各种链表反转问题。

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

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

相关文章

跨平台游戏引擎 Axmol-2.8.1 发布

所有使用 axmol-2.8.0 的开发者都应更新至此版本 Axmol 2.8.1 版本是一个以错误修复和功能改进为主的次要 LTS 长期支持版本&#xff0c;发布时间: 2025 年 9 月 5 日 &#x1f64f;感谢所有对 axmol 项目的贡献者&#xff0c;包括财务赞助者&#xff1a;scorewarrior、peter…

通过PXE的方式实现Ubuntu 24.04 自动安装

PXE自动化安装Ubuntu 24.04的配置文件之前都是通过PXE来自动化安装Redhat系列的&#xff0c;例如&#xff1a;Rocky9、Rocky10、CentOS7、银河麒麟 Kylin-V10、Kylin-V11、OpenEuler 24.03等。现在安装Ubuntu系列的跟红帽的不太一样&#xff0c;所以在这里介绍下。创建三个文件…

AOSP Framework开发的一些超方便的快捷命令

在系统源码中发现的一些命令和快捷方式。我们在编译源码之前执行的source build/envsetup.sh,通过cat build/envsetup.sh发现如下命令 - lunch: lunch <product_name>-<build_variant>Selects <product_name> as the product to build, and <build_…

【Protues仿真】基于AT89C52单片机的数码管驱动事例

目录 0案例视频效果展示 1 AT89C52单片机驱动单个数码管 1.1 数码管基础知识 1.1.1外观与引脚 1.1.2 共阴(CC) vs 共阳(CA) 1.1.3段码表(以数字1为例) 1.1.4驱动方式A. 直连IO(最简单,占用IO多)一个段一根线,共阴或共阳公共端固定接GND/VCC。适合单个数码管、…

01-Redis 发展简史与核心定位解析:从诞生到三大产品矩阵

目录引言一、Redis 的起源与发展&#xff1a;从定制工具到开源生态二、Redis 的核心定位&#xff1a;不止是缓存的多面手三、Redis 三大产品矩阵&#xff1a;按需选择的完整解决方案3.1 Redis Open Source&#xff08;社区版&#xff09;&#xff1a;入门与轻量场景首选3.2 Red…

记录jilu~

centos1、安装最小版Linux 安装必要工具yum -install -y epel-releaseyum -install -y net-toolsyum -install -y vim2、修改hostname hostnamectl net-hostname newhostname3、网络配置文件&#xff0c;网关 &#xff0c; 使用ip &#xff0c;dns。。/etc/sysconfig/network-s…

【Linux基础】fdisk命令详解:从入门到精通的磁盘分区管理完全指南

目录 前言 1 fdisk命令概述 1.1 什么是fdisk 1.2 fdisk的应用场景 1.3 fdisk与其他分区工具的比较 2 fdisk命令的安装与基本语法 2.1 在不同Linux发行版中安装fdisk 2.2 fdisk的基本语法 3 fdisk命令参数详解 3.1 主要参数说明 3.2 交互式命令 4 fdisk操作流程详解…

Flowable 工作流引擎

1、核心类 Flowable 引擎通过 ProcessEngine 作为总入口点&#xff0c;提供了多个核心服务接口&#xff0c;每个服务都负责特定的功能领域&#xff1a;服务名称 (Service Name)主要功能 (Main Functionality)关键操作 (Key Operations)RepositoryService管理流程定义和部署&…

(RDFS)随机深度特征选择方法解释:简而言之,RDFS主要针对的是恶意的服务器,它建立在客户端是诚实的前提下。

1. 随机深度特征选择是怎么实现的&#xff1f;随机深度特征选择 是一种在分布式机器学习&#xff08;特别是联邦学习&#xff09;中用于保护客户端数据隐私的技术。它的核心思想是&#xff1a;在每一轮训练中&#xff0c;每个客户端随机选择模型的一个子集&#xff08;即“深度…

C++20格式化字符串:std::format的使用与实践

在C编程中&#xff0c;字符串格式化是一项常见的任务。在C20引入std::format之前&#xff0c;开发者通常依赖于一些传统的解决方案&#xff0c;如printf系列函数、sstream&#xff0c;或者第三方库如boost.format。然而&#xff0c;这些方法在代码可读性、类型安全性和灵活性方…

【漏洞复现】CVE-2025-8088|WinRAR 路径穿越漏洞:从原理到蓝屏攻击全流程

【漏洞复现】CVE-2025-8088&#xff5c;WinRAR 路径穿越漏洞&#xff1a;从原理到蓝屏攻击全流程 前言 WinRAR 作为 Windows 平台最常用的压缩管理工具之一&#xff0c;几乎是每台电脑的 “标配软件”。但在 2025 年 8 月&#xff0c;一款影响范围覆盖 WinRAR 0 至 7.12 全版本…

uniapp中使用echarts并且支持pc端的拖动、拖拽和其他交互事件

npm install echarts -D ​ // "echarts": "^5.3.2", [推荐版本] // "zrender": "^5.3.2" [如果报错的话就安装这个]<template><view class"container"><view id"myChart" class"chart"…

Qt中QProxyStyledrawControl函数4个参数的意义

Qt中QProxyStyle::drawControl函数4个参数的意义 我们来详细解释一下 Qt 中 QProxyStyle::drawControl 函数的四个参数。 这个函数是 Qt 样式系统中的一个核心方法&#xff0c;用于绘制标准 UI 元素&#xff08;如按钮、复选框、菜单栏等&#xff09;。当你继承 QProxyStyle 并…

idf-esp32 PWM呼吸灯(LEDC头文件)

相关宏和变量#define LED_PIN GPIO_NUM_3 #define LEDC_CHANNEL LEDC_CHANNEL_0 #define LEDC_TIMER LEDC_TIMER_0 #define LEDC_MODE LEDC_LOW_SPEED_MODE #define LEDC_DUTY_RES LEDC_TIMER_13_BIT // 2^13 8192级亮度 #define LEDC_FREQUENCY 50…

PLC_博图系列☞基本指令”S_ODTS:分配保持型接通延时定时器参数并启动“

PLC_博图系列☞基本指令”S_ODTS&#xff1a;分配保持型接通延时定时器参数并启动“ 文章目录PLC_博图系列☞基本指令”S_ODTS&#xff1a;分配保持型接通延时定时器参数并启动“背景介绍S_ODTS&#xff1a; 分配保持型接通延时定时器参数并启动说明参数脉冲时序图示例关键字&a…

OneCode 可视化揭秘系列(三):AI MCP驱动的智能工作流逻辑编排

OneCode 可视化揭秘系列&#xff08;三&#xff09;&#xff1a;AI MCP驱动的智能工作流逻辑编排 引言 在前两篇系列博文中&#xff0c;我们详细探讨了OneCode可视化动作的基础配置与界面设计&#xff0c;以及组件交互与数据流管理。在本篇文章中&#xff0c;我们将深入剖析逻辑…

TypeORM、Sequelize、Hibernate 的优缺点对比:新手常见 SQL 与 ORM 踩坑总结

1. ORM 与关系型数据库&#xff08;MySQL、PostgreSQL&#xff09; 的使用 SQL 语句编写&#xff08;JOIN、GROUP BY、索引使用、事务控制&#xff09;与 ORM 映射&#xff08;如 Sequelize、TypeORM、Hibernate&#xff09;之间的差异会让新手非常纠结&#xff1b;尤其是理解…

JavaScript 创建型设计模式详解

1. 单例模式1.1. 使用场景在前端开发中&#xff0c;全局状态管理、配置信息、数据库连接等往往需要在应用中只存在一个实例&#xff0c;避免多次实例化带来的数据不一致性。例如&#xff0c;在一个前端应用中&#xff0c;全局的 loading 状态通常需要一个单例模式来确保其唯一性…

k8s除了主server服务器可正常使用kubectl命令,其他节点不能使用原因,以及如何在其他k8s节点正常使用kubectl命令??

kubectl 并不是“只能”在主节点&#xff08;Control Plane Node&#xff09;使用&#xff0c;而是因为它需要访问 Kubernetes 的 kube-apiserver&#xff0c;而 kube-apiserver 通常只在主节点上运行并监听内部网络。简单来说kubectl 需要连接 kube-apiserver&#xff01;&…

Custom SRP - Complex Maps

https://catlikecoding.com/unity/tutorials/custom-srp/complex-maps/1 创建材质球我们的材质已经支持光照,并且支持 Albedo 和 Emission 贴图.创建材质球,并应用下面的电路板的图分别作为 albedo emission设置材质球的金属度为 1 , 光滑度为 0.952 Mask Map在 albedo 图上的不…