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

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

一、双指针技术分类

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

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

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

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

二、典型应用与算法实现

2.1 链表逆序

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

python

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

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

python

def reverseList(head):
    if not head or not head.next:
        return head
    new_head = reverseList(head.next)
    head.next.next = head
    head.next = None
    return 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.next
        fast = fast.next
    return slow.val

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

2.3 删除倒数第 n 个节点

python

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

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

2.4 检测链表环存在性

python

def hasCycle(head):
    slow = fast = head
    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next
        if slow == fast:
            return True
    return False

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

2.5 计算环入口和长度

python

def detectCycle(head):
    # 第一步:检测是否存在环
    slow = fast = head
    has_cycle = False
    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next
        if slow == fast:
            has_cycle = True
            break
    if not has_cycle:
        return None
    
    # 第二步:找到环入口
    ptr1 = head
    ptr2 = slow
    while ptr1 != ptr2:
        ptr1 = ptr1.next
        ptr2 = ptr2.next
    return ptr1

def calculateCycleLength(head):
    # 先找到环内节点
    slow = fast = head
    while fast and fast.next:
        slow = slow.next
        fast = fast.next.next
        if slow == fast:
            break
    
    # 计算环长度
    count = 0
    while True:
        slow = slow.next
        count += 1
        if slow == fast:
            break
    return 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)
  • 数组问题:双指针法解决两数之和、三数之和等问题

相关文章:

  • springboot433-基于SpringBoot的流浪猫爱心救助系统(源码+数据库+纯前后端分离+部署讲解等)
  • Fast DDS Security--多方密钥协商协议
  • 人脸识别之数据集中 PI20 和 CFMT 之间关联的模型预测贝叶斯(Python+论文代码实现)
  • 接口使用实例和Object类及内部类
  • 本地部署 DeepSeek R1 的几种常见方法
  • 在 UniApp 开发的网站中使图片能够缓存,不一直刷新
  • 委外订单不能删除提示领料未发量不能小于零
  • 【 PyQt】事件的触发:信号与槽
  • GitHub 项目版本管理与 Release 发布流程记录
  • HTTPS工作原理与安全机制详解(仅供参考)
  • 【RabbitMQ】事务
  • 查看端口被占用命令
  • FX-函数重载、重写(覆盖)、隐藏
  • Rust与Cargo版本关系(Rust版本、rustc、rustup)
  • 信息安全意识之安全组织架构图
  • ubuntu 24.04通过Flatpak安装迅雷
  • Dom详解
  • 02 | 快速部署 fastgo 项目
  • 在 Spring Boot 中实现基于 TraceId 的日志链路追踪
  • vue3-element-admin 前后端本地启动联调
  • 冰雹造成车损能赔吗?如何理赔?机构答疑
  • 中拉论坛部长级会议为何悬挂海地和圣卢西亚的国旗?外交部回应
  • 多家中小银行存款利率迈入“1时代”
  • 瑞士联邦主席凯勒-祖特尔、联邦副主席帕姆兰会见何立峰
  • 祝贺!苏翊鸣成功解锁“2160”
  • 梅花奖在上海|第六代“杨子荣”是怎样炼成的?