十二天-双指针技术:链表问题的高效解法

一、双指针技术分类

1. 同速双指针(同向移动)

  • 特点:两个指针以相同速度移动
  • 适用场景
    • 链表逆序
    • 查找倒数第 k 个元素
    • 删除倒数第 n 个节点

2. 快慢双指针(异速移动)

  • 特点:一个指针每次移动 1 步,另一个移动 2 步
  • 适用场景
    • 检测链表环存在性
    • 计算环入口和长度
    • 寻找中间节点

二、典型应用与算法实现

2.1 链表逆序

方法一:迭代法(同速双指针)

python

def reverseList(head):prev = Nonecurr = headwhile curr:next_node = curr.next  # 保存后续节点curr.next = prev       # 反转指针方向prev = curr            # 双指针同步移动curr = next_nodereturn prev  # prev最终指向新头节点

  • 复杂度:O (n) 时间,O (1) 空间
方法二:递归法

python

def reverseList(head):if not head or not head.next:return headnew_head = reverseList(head.next)head.next.next = headhead.next = Nonereturn new_head

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

2.2 查找倒数第 k 个元素

python

def findKthFromEnd(head, k):slow = fast = head# 快指针先走k步for _ in range(k):fast = fast.next# 双指针同步移动while fast:slow = slow.nextfast = fast.nextreturn slow.val

  • 关键点:快慢指针间距保持 k,当快指针到达末尾时,慢指针指向目标节点

2.3 删除倒数第 n 个节点

python

def removeNthFromEnd(head, n):dummy = ListNode(0, head)first = dummysecond = dummy# 快指针先走n+1步for _ in range(n+1):first = first.next# 同步移动直到快指针到达末尾while first:first = first.nextsecond = second.next# 删除操作second.next = second.next.nextreturn dummy.next

  • 技巧:使用虚拟头节点避免处理头节点删除的边界情况

2.4 检测链表环存在性

python

def hasCycle(head):slow = fast = headwhile fast and fast.next:slow = slow.nextfast = fast.next.nextif slow == fast:return Truereturn False

  • 原理:若存在环,快慢指针必然相遇

2.5 计算环入口和长度

python

def detectCycle(head):# 第一步:检测是否存在环slow = fast = headhas_cycle = Falsewhile fast and fast.next:slow = slow.nextfast = fast.next.nextif slow == fast:has_cycle = Truebreakif not has_cycle:return None# 第二步:找到环入口ptr1 = headptr2 = slowwhile ptr1 != ptr2:ptr1 = ptr1.nextptr2 = ptr2.nextreturn ptr1def calculateCycleLength(head):# 先找到环内节点slow = fast = headwhile fast and fast.next:slow = slow.nextfast = fast.next.nextif slow == fast:break# 计算环长度count = 0while True:slow = slow.nextcount += 1if slow == fast:breakreturn count

三、算法复杂度对比

问题类型双指针方法时间复杂度空间复杂度优势
链表逆序迭代O(n)O(1)无栈溢出风险
查找倒数第 k 元素快慢指针O(n)O(1)仅需一次遍历
删除倒数第 n 节点快慢指针O(n)O(1)无需预先计算长度
检测环存在性快慢指针O(n)O(1)最优解法
环入口定位双指针定位O(n)O(1)Floyd 判圈算法变种

四、优化建议与应用场景

1. 优化技巧

  • 虚拟头节点:处理头节点删除时,避免复杂的边界判断
  • 指针间距控制:通过调整快慢指针的初始间距,解决不同问题
  • 两次遍历:在检测环问题中,先用快慢指针检测环,再用同速指针定位入口

2. 典型应用场景

  • 链表操作:LeetCode 206(反转链表)、19(删除倒数第 N 个节点)
  • 环检测:LeetCode 141(环形链表)、142(环形链表 II)
  • 数组问题:双指针法解决两数之和、三数之和等问题

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

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

相关文章

【vllm】Qwen2.5-VL-72B-AWQ 部署记录

版本:0.7.2 注意事项: export LD_LIBRARY_PATH/home/xxxxx/anaconda3/envs/xxxxx/lib/python3.10/site-packages/nvidia/nvjitlink/lib:$LD_LIBRARY_PATH # 如果报错可能需要Also pip install --force-reinstall githttps://github.com/huggingface/tra…

深度学习与大模型-张量

大家好!今天我们来聊聊张量(Tensor)。别被这个词吓到,其实它没那么复杂。 什么是张量? 简单来说,张量就是一个多维数组。你可以把它看作是一个装数据的容器,数据的维度可以是一维、二维&#…

【前端面试题】Vu3常见的面试题

1.Vue3与 Vue2的核心区别有哪些? ‌ 响应式系统 ‌: ‌ Vue2:通过Object.defineProperty 实现响应式。这种方式在处理对象属性的添加和删除时存在局限性,且无法直接监控数组的变化 ‌;‌Vue3:采用Proxy 实现响应式&…

Android 粘包与丢包处理工具类:支持多种粘包策略的 Helper 实现

在Android开发中,处理TCP/UDP通信时,粘包和丢包是常见的问题。粘包是指多个数据包被接收方一次性接收,导致数据包之间的界限不清晰;丢包则是指数据包在传输过程中丢失。为了处理这些问题,我们可以编写一个帮助类 Packe…

【C++11】移动语义

回顾 const int c的c是可以被取地址的,尽管是常量。所以以是否为常量来判断是否为右值是错误的。 左值与右值正确的区分方法是是否能够被取地址。(能被取地址也就代表着是一个持久状态,即有持久的存储空间的值) 常见的左值有我们…

LangChain教程 - Agent -之 ZERO_SHOT_REACT_DESCRIPTION

在构建智能 AI 助手时,我们希望模型能够智能地调用工具,以便提供准确的信息。LangChain 提供了 AgentType.ZERO_SHOT_REACT_DESCRIPTION,它结合了 ReAct(Reasoning Acting)策略,使得 LLM 可以基于工具的描…

移动Android和IOS自动化中常见问题

APP测试逻辑 在app编写自动化测试用例时,通常会出现只是简单的点点点过程,然而却忽略了在实际的自动化实现过程中,软件是对app元素的判断来执行测试脚本。所以会出现在后期已经写好自动化脚本之后还会对测试用例的更新。 App在测试时&#…

python高效试用17---两个字符串组成一个新的字符串和两个字符串组成元组作为key哪个更高效

在 Python 中,使用字符串连接 (str1 str2) 作为 key 和使用元组 ((str1, str2)) 作为 key 的效率差异,主要受以下因素影响: 哈希计算速度: 字符串连接 (str1 str2):会创建一个新的字符串对象,并计算哈希…

深入浅出Java try-with-resources:告别资源泄漏的烦恼

一、为什么需要try-with-resources? 在Java开发中,我们经常需要处理各种资源:文件流、数据库连接、网络套接字等。这些资源都有一个共同特点——必须在使用后正确关闭。传统的资源管理方式存在三大痛点: 代码臃肿:每…

Python+DeepSeek:开启AI编程新次元——从自动化到智能创造的实战指南

文章核心价值 技术热点:结合全球最流行的编程语言与国产顶尖AI模型实用场景:覆盖代码开发/数据分析/办公自动化等高频需求流量密码:揭秘大模型在编程中的创造性应用目录结构 环境搭建:5分钟快速接入DeepSeek场景一:AI辅助代码开发(智能补全+调试)场景二:数据分析超级助…

Linux tcpdump -any抓的包转换成标准的pcap

在 Linux 中使用 tcpdump -any 抓包并转换为标准 pcap 文件时出现额外字段,通常与 链路层协议头部的差异 以及 pcap 文件格式的兼容性 有关。以下是详细原因和解决方案: 一、问题原因分析 -any 选项的局限性 tcpdump -any 会自动猜测链路层协议类型(如 Ethernet、IEEE 802…

【SpringMVC】深入解析使用 Postman 在请求中传递对象类型、数组类型、参数类型的参数方法和后端参数重命名、及非必传参数设置的方法

SpringMVC—请求传参 1. 传递对象 如果参数比较多时,方法声明就需要有很多形参;并且后续每次新增一个参数,也需要修改方法声明. 我们不妨把这些参数封装为一个对象; Spring MVC 也可以自动实现对象参数的赋值,比如 Us…

一个差劲的软件设计

项目概况: 之前自己设计并开发了一个用C#开发的上位机软件,整个软件只有一个Form,一个TabControl,3个TabControlPanel,总共100多个lable、textbox、ListBox等控件都放在这3个TabControlPanel里。 问题: 1.…

Linux练级宝典->进程控制详解(进程替换,fork函数)

目录 进程创建 fork函数 写时拷贝 进程终止 进程退出码 exit函数 _exit函数 return,exit _exit之间的区别和联系 进程等待 进程等待的必要性 获取子进程status 进程等待的方法 wait waipid 多子进程创建理解 非阻塞轮询检测子进程 进程程序替换 替…

RabbitMq--消息可靠性

12.消息可靠性 1.消息丢失的情况 生产者向消息代理传递消息的过程中,消息丢失了消息代理( RabbitMQ )把消息弄丢了消费者把消息弄丢了 那怎么保证消息的可靠性呢,我们可以从消息丢失的情况入手——从生产者、消息代理&#xff0…

Windows中在VSCode/Cursor上通过CMake或launch文件配置CUDA编程环境

前置步骤 安装符合GPU型号的CUDA Toolkit 配置好 nvcc 环境变量 安装 Visual Studio 参考https://blog.csdn.net/Cony_14/article/details/137510909 VSCode 安装插件 Nsight Visual Studio Code Edition 注意:不是vscode-cudacpp。若两个插件同时安装,…

Spark(8)配置Hadoop集群环境-使用脚本命令实现集群文件同步

一.hadoop的运行模式 二.scp命令————基本使用 三.scp命令———拓展使用 四.rsync远程同步 五.xsync脚本集群之间的同步 一.hadoop的运行模式 hadoop一共有如下三种运行方式: 1. 本地运行。数据存储在linux本地,测试偶尔用一下。我们上一节课使用…

聚焦两会:科技与发展并进,赛逸展2025成创新新舞台

在十四届全国人大三次会议和全国政协十四届三次会议期间,代表委员们围绕多个关键议题展开深入讨论,为国家未来发展谋篇布局。其中,技术竞争加剧与经济转型需求成为两会焦点,将在首都北京举办的2025第七届亚洲消费电子技术贸易展&a…

【音视频】ffmpeg命令提取像素格式

1、提取YUV数据 提取yuv数据,并保持分辨率与原视频一致 使用-pix_fmt或-pixel_format指定yuv格式提取数据,并保持原来的分辨率 ffmpeg -i music.mp4 -t "01:00" -pixel_format yuv420p music.yuv提取成功后,可以使用ffplay指定y…

【从零开始学习计算机科学】计算机体系结构(二)指令级并行(ILP)

【从零开始学习计算机科学】【从零开始学习计算机科学】计算机体系结构(二)指令级并行(ILP) ILP流水线(pipeline)流水线调度循环展开和循环流水循环展开。循环展开的具体步骤可以描述为,软件流水(循环流水)。我们可以通过流水线的思想处理循环的执行,即不需要这一次的…