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

1、双指针法

一、了解双指针

双指针(Two Pointers)是一种常用的算法技巧,通常用于解决数组或链表中的问题。它的核心思想是使用两个指针(或索引)在数据结构中遍历或搜索,从而高效地解决问题。双指针技巧通常可以将时间复杂度从 (O(n^2)) 优化到 (O(n))。

推荐先看这个视频,再看下面文章


二、 双指针的常见应用场景

  1. 有序数组的两数之和

    • 给定一个有序数组和一个目标值,找到两个数使它们的和等于目标值。
    • 使用双指针,一个指向数组开头,一个指向数组末尾,根据和的大小移动指针。
  2. 移除数组中的重复元素

    • 给定一个有序数组,原地移除重复元素。
    • 使用双指针,一个指针用于遍历数组,另一个指针用于记录非重复元素的位置。
  3. 滑动窗口问题

    • 给定一个数组和一个窗口大小,找到满足条件的子数组。
    • 使用双指针表示窗口的左右边界,根据条件滑动窗口。
  4. 链表的快慢指针

    • 判断链表是否有环,或找到链表的中间节点。
    • 使用快慢指针,快指针每次移动两步,慢指针每次移动一步。

二、 双指针的技巧总结

1. 对撞指针

对撞指针 是一种常用的双指针技巧,通常用于解决数组或字符串中的问题。它的核心思想是使用两个指针,一个从数组的起始位置(左指针)开始,另一个从数组的末尾位置(右指针)开始,通过向中间移动来解决问题。


1.1、对撞指针的核心思想

  1. 指针的初始化

    • 左指针 l 指向数组的起始位置(l = 0)。
    • 右指针 r 指向数组的末尾位置(r = nums.size() - 1)。
  2. 指针的移动规则

    • 根据问题的要求,决定左指针或右指针的移动方向。
    • 通常,左指针向右移动,右指针向左移动。
  3. 终止条件

    • 当左指针和右指针相遇或交叉时,算法结束。

1.2、对撞指针的总结

  1. 适用场景

    • 有序数组中的两数之和、三数之和。
    • 反转数组或字符串。
    • 验证回文串。
    • 盛最多水的容器。
  2. 核心思想

    • 使用两个指针从数组的两端向中间移动,通过比较指针指向的元素来解决问题。
  3. 时间复杂度

    • 通常为 (O(n)),因为每个元素最多被访问一次。
  4. 空间复杂度

    • 通常为 (O(1)),只使用了常数级别的额外空间。

2. 快慢指针

快慢指针 是一种常用的双指针技巧,通常用于解决链表或数组中的问题。它的核心思想是使用两个指针,一个移动速度快(快指针),一个移动速度慢(慢指针),通过它们的相对移动来解决问题。


2.1、快慢指针的核心思想

  1. 快指针和慢指针的移动速度

    • 快指针每次移动两步。
    • 慢指针每次移动一步。
  2. 相对速度

    • 快指针和慢指针的相对速度是 1,即快指针每次比慢指针多走一步。
  3. 终止条件

    • 当快指针到达链表末尾(或数组末尾)时,慢指针通常指向目标位置。

2.2、快慢指针的总结

  1. 适用场景

    • 链表中的环检测、中间节点查找。
    • 数组中的重复元素删除、重复数查找。
  2. 核心思想

    • 快指针和慢指针以不同的速度移动,通过相对速度解决问题。
  3. 时间复杂度

    • 通常为 (O(n)),因为每个元素最多被访问两次。
  4. 空间复杂度

    • 通常为 (O(1)),只使用了常数级别的额外空间。

3. 滑动窗口

3.1、滑动窗口的两种情况

3.1.1、情况1:固定大小的窗口
  • 特点
    • 窗口的大小是固定的。
    • 通常用于解决需要在固定长度的子数组或子串中查找满足条件的问题。
  • 示例问题
    • 在一个数组中,找到长度为 k 的连续子数组,使得子数组的和大于 target
  • 解决方法
    • 初始化左指针 l = 0,右指针 r = k - 1
    • 计算窗口内的和,如果满足条件,返回结果。
    • 如果不满足条件,移动窗口:l++r++,继续检查新的窗口。
3.1.2、情况2:可变大小的窗口
  • 特点
    • 窗口的大小不固定。
    • 通常用于解决需要在不定长度的子数组或子串中查找满足条件的问题。
  • 示例问题
    • 在一个数组中,找到和大于等于 target 的最短连续子数组。
  • 解决方法
    • 初始化左指针 l = 0,右指针 r = 0
    • 右指针 r 向右移动,扩大窗口,直到窗口内的和满足条件。
    • 左指针 l 向右移动,缩小窗口,尝试找到更短的满足条件的子数组。

3.4、滑动窗口的核心思想

  1. 窗口的定义

    • 窗口是数组或字符串中的一个连续子区间,由左指针 l 和右指针 r 定义。
  2. 窗口的移动

    • 扩大窗口:右指针 r 向右移动,增加窗口的大小。
    • 缩小窗口:左指针 l 向右移动,减少窗口的大小。
  3. 条件的判断

    • 在窗口移动的过程中,根据问题的要求判断当前窗口是否满足条件。

4. 分离指针

分离指针 是一种双指针技巧,通常用于解决涉及多个数组或链表的问题。它的核心思想是使用两个指针分别遍历不同的数组或链表,通过它们的相对移动来解决问题。


4.1、分离指针的常见应用场景

  1. 合并两个有序数组或链表

    • 将两个有序数组合并为一个有序数组。
    • 将两个有序链表合并为一个有序链表。
  2. 查找两个数组的交集

    • 找到两个有序数组的交集。
  3. 判断一个数组是否是另一个数组的子序列

    • 判断一个数组是否是另一个数组的子序列。
  4. 滑动窗口问题

    • 使用两个指针分别表示窗口的左右边界。

4.2、分离指针的核心思想

  1. 指针的初始化

    • 每个指针分别指向一个数组或链表的起始位置。
  2. 指针的移动规则

    • 根据问题的要求,决定每个指针的移动方向。
    • 通常,指针的移动方向是单向的(从左到右)。
  3. 终止条件

    • 当某个指针到达数组或链表的末尾时,算法结束。

4.3、分离指针的总结

  1. 适用场景

    • 合并两个有序数组或链表。
    • 查找两个数组的交集。
    • 判断一个数组是否是另一个数组的子序列。
  2. 核心思想

    • 使用两个指针分别遍历不同的数组或链表,通过比较指针指向的元素来解决问题。
  3. 时间复杂度

    • 通常为 (O(m + n)),其中 (m) 和 (n) 是两个数组或链表的长度。
  4. 空间复杂度

    • 通常为 (O(1)),只使用了常数级别的额外空间。

三、 双指针的时间复杂度

  • 双指针通常可以将时间复杂度从 (O(n^2)) 优化到 (O(n)),因为每个指针最多遍历数组或链表一次。

四、例题

  • 对撞指针
    力扣hot100两数之和
  • 快慢指针
    力扣hot100移动零
  • 滑动窗口
    力扣LCR长度最小的子数组
  • 分离指针
    力扣21、合并2个有序链表

相关文章:

  • 自由学习记录(46)
  • UE4学习笔记 FPS游戏制作11 把枪提出为对象
  • 2025.3.23机器学习笔记:文献阅读
  • soft回归用内置函数
  • 软考-高项,知识点一览八 整合管理
  • CUDA Lazy Loading:优化GPU程序初始化与内存使用的利器
  • 【蓝桥杯】12111暖气冰场(多源BFS 或者 二分)
  • ‘闭包‘, ‘装饰器‘及其应用场景
  • 西门子200smart之modbus_TCP(做从站与第三方设备)通讯
  • 从头开始学C语言第二十九天——指针数组
  • JavaScript-日期对象与节点操作详解
  • Apache Flink技术原理深入解析:任务执行流程全景图
  • Rocky9.2 编译安装Intel WIFI系列无线网卡驱动
  • 华为终端将全面进入鸿蒙时代
  • LLM - CentOS上离线部署Ollama+Qwen2.5-coder模型完全指南
  • Mimalloc论文解析:小内存管理的极致追求与实践启示
  • 虚拟机访问主机的plc仿真
  • C++学习之网盘项目单例模式
  • Swift 经典链表面试题:如何在不访问头节点的情况下删除指定节点?
  • FPGA 以太网通信(四)网络视频传输系统
  • 体坛联播|巴萨提前2轮西甲夺冠,郑钦文不敌高芙止步4强
  • 科普|男性这个器官晚到岗,可能影响生育能力
  • 娃哈哈:自4月起已终止与今麦郎的委托代工关系,未来将坚持自有生产模式
  • “老中青少”四代同堂,季春艳携锡剧《玲珑女》冲击梅花奖
  • 美政府以拨款为要挟胁迫各州服从移民政策,20个州联合起诉
  • 著名连环画家庞邦本逝世