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

【数据结构与算法学习笔记】双指针

前言

本文为个人学习的算法学习笔记,学习笔记,学习笔记不是经验分享与教学,不是经验分享与教学,不是经验分享与教学,若有错误各位大佬轻喷(T^T)。主要使用编程语言为Python3,各类资料题目源于网络,主要自学途径为博学谷,侵权即删。

一、双指针概述

双指针是程序设计中核心优化技巧之一,核心原理是通过两个指针(或索引) 在数据结构(如链表、数组)上协同移动,依据不同移动策略解决特定问题,其核心价值在于将暴力解法的时间复杂度(如 O (n²))优化为线性复杂度(O (n)),且通常仅需 O (1) 额外空间,是竞赛初赛的高频考点之一。

根据指针移动方向的差异,将双指针分为快慢指针左右指针两类,二者适用场景、移动逻辑存在显著差异,下文将结合课件内容详细拆解。

二、双指针类型一:快慢指针

1. 定义与核心特点

  • 移动方向:同向移动(沿数据结构同一方向,如均从链表头向链表尾移动)
  • 移动策略:两个指针移动速度不同(如快指针每次走 2 步,慢指针每次走 1 步)或遵循不同触发条件
  • 适用场景:主要用于链表,解决 “链表环检测”“特定节点查找”(如链表中间节点、倒数第 K 个节点)等问题
  • 核心优势:无需额外存储空间,仅通过 “速度差” 定位目标,效率高且实现简洁

2. 典型例题:LeetCode 141. 环形链表(课件重点案例)

(1)题目背景(课件提及)

给定一个链表的头节点head,判断链表是否存在环(即某节点的next指针指向已遍历过的节点,形成闭环),存在则返回true,否则返回false

(2)解题思路(基于课件逻辑)

类比 “环形跑道跑步”:若两人在环形跑道上跑步,速度快者终将追上速度慢者;若为直线跑道,速度快者会先到达终点。基于此设计如下步骤:

  1. 初始化指针:快慢指针均从链表头节点出发(slow = headfast = head),为避免初始状态下两指针相等的误判,可让fast先移动 1 步(fast = head.next);
  2. 设定移动规则:慢指针每次移动 1 步(slow = slow.next),快指针每次移动 2 步(fast = fast.next.next);
  3. 判断逻辑
    • 若链表无环:快指针会先到达链表尾部(fast == Nonefast.next == None),直接返回false
    • 若链表有环:快指针会在环内追上慢指针(slow == fast),返回true
(3)Python 代码实现
# 定义链表节点结构(符合课件中链表的节点构成逻辑)
class ListNode:def __init__(self, x):self.val = xself.next = Noneclass Solution:def hasCycle(self, head: ListNode) -> bool:# 边界条件:空链表或仅1个节点,必然无环(课件隐含边界处理逻辑)if not head or not head.next:return False# 初始化快慢指针:快指针先移动1步,避免初始相等误判slow = headfast = head.next# 循环移动指针,直到相遇或快指针到达尾部while slow != fast:# 快指针到达尾部(无环),直接返回falseif not fast or not fast.next:return Falseslow = slow.next  # 慢指针走1步fast = fast.next.next  # 快指针走2步# 快慢指针相遇,存在环return True

3. 举一反三:快慢指针的其他应用(课件提及场景)

(1)LeetCode 876. 链表的中间结点
  • 题目需求:找到非空链表的中间节点,若节点数为偶数,返回第二个中间节点(如链表1→2→3→4,返回3);
  • 解题思路(课件逻辑)
    1. 快慢指针同时从head出发,快指针每次走 2 步,慢指针每次走 1 步;
    2. 当快指针到达尾部(fast == Nonefast.next == None)时,慢指针恰好指向中间节点;
  • Python 代码实现
class Solution:def middleNode(self, head: ListNode) -> ListNode:slow = fast = head# 快指针未到尾部时,持续移动while fast and fast.next:slow = slow.next  # 慢指针1步fast = fast.next.next  # 快指针2步# 快指针到达尾部,慢指针指向中间节点return slow
(2)查找链表的倒数第 K 个节点(课件拓展场景)
  • 题目需求:给定链表,找到从末尾数第 K 个节点(如链表1→2→3→4→5,K=2,返回4);
  • 解题思路(课件逻辑)
    1. 快指针先出发,向前移动 K 步(与慢指针拉开 K 个节点的距离);
    2. 快慢指针再同时以 1 步 / 次的速度移动;
    3. 当快指针到达尾部(fast == None)时,慢指针指向的即为倒数第 K 个节点;
  • Python 代码实现
class Solution:def getKthFromEnd(self, head: ListNode, k: int) -> ListNode:slow = fast = head# 快指针先移动K步for _ in range(k):if not fast:  # 若K大于链表长度,返回None(边界处理)return Nonefast = fast.next# 快慢指针同时移动,直到快指针到达尾部while fast:slow = slow.nextfast = fast.nextreturn slow

4. 快慢指针小结(基于课件内容)

  • 核心逻辑:通过 “速度差” 制造指针间的固定距离或相对运动,从而定位环、中间节点等目标;
  • 关键注意事项:
    1. 边界处理:需避免快指针访问None.next(需判断fastfast.next是否为None);
    2. 初始位置:根据题目需求调整(如环形链表需让快指针先移动 1 步,避免初始误判)。

三、双指针类型二:左右指针

1. 定义与核心特点

  • 移动方向:相向移动(从数据结构两端向中间移动,如左指针从数组起始索引 0 出发,右指针从数组末尾索引len(arr)-1出发);
  • 移动策略:根据题目条件判断移动左指针或右指针,直到两指针相遇(left >= right);
  • 适用场景:主要用于数组(尤其有序数组),解决 “盛最多水的容器”“两数之和”“区间查找” 等问题;
  • 核心优势:将暴力枚举的 O (n²) 时间复杂度降至 O (n),且无需额外空间。

2. 典型例题:LeetCode 11. 盛最多水的容器(课件重点案例)

(1)题目背景(课件提及)

给定非负整数数组height,每个元素代表柱子高度(横坐标为索引,纵坐标为高度),选择两根柱子与 x 轴组成容器,求容器能容纳的最大水量,水量计算公式为W(i,j) = Min(height[i], height[j]) * (j-i)i<j)。

(2)解题思路(基于课件逻辑)

容器水量由 “最短柱子高度” 和 “柱子间距” 共同决定,核心是通过 “两端收缩” 寻找最优组合:

  1. 初始化指针:左指针left=0(数组起始),右指针right=len(height)-1,记录最大水量max_water=0
  2. 计算当前水量:按公式计算current_water = min(height[left], height[right]) * (right - left),若current_water > max_water,则更新max_water
  3. 指针移动规则(课件关键结论):
    • height[left] < height[right]:移动左指针(left += 1)—— 此时容器高度由左柱子决定,移动右指针会减小间距且无法提升高度,水量必然减少;移动左指针可能遇到更高柱子,有机会提升水量;
    • height[left] >= height[right]:移动右指针(right -= 1),逻辑同上;
  4. 循环终止:当left >= right时,遍历结束,返回max_water
(3)Python 代码实现
class Solution:def maxArea(self, height: list[int]) -> int:left = 0right = len(height) - 1max_water = 0while left < right:# 计算当前水量(按课件公式W(i,j)计算)current_height = min(height[left], height[right])current_width = right - leftcurrent_water = current_height * current_width# 更新最大水量if current_water > max_water:max_water = current_water# 按课件规则移动指针:移动较矮的柱子对应的指针if height[left] < height[right]:left += 1else:right -= 1return max_water

3. 举一反三:左右指针的其他应用(课件提及场景)

LeetCode 167. 两数之和 II - 输入有序数组
  • 题目需求:给定非递减排序的数组numbers和目标值target,找出两个数使其和为target,返回两数的索引(从 1 开始计数,答案唯一);
  • 解题思路(课件逻辑):利用数组有序特性,通过 “两端收缩” 缩小范围:
    1. 初始化left=0right=len(numbers)-1
    2. 计算当前和sum = numbers[left] + numbers[right]
      • sum == target:返回[left+1, right+1](索引从 1 开始,符合题目要求);
      • sum < target:移动左指针(left += 1)—— 需更大的数补充和;
      • sum > target:移动右指针(right -= 1)—— 需更小的数减少和;
  • Python 代码实现
class Solution:def twoSum(self, numbers: list[int], target: int) -> list[int]:left = 0right = len(numbers) - 1while left < right:current_sum = numbers[left] + numbers[right]if current_sum == target:return [left + 1, right + 1]  # 索引从1开始elif current_sum < target:left += 1  # 和偏小,移动左指针找更大的数else:right -= 1  # 和偏大,移动右指针找更小的数return []  # 题目保证有答案,此句仅为语法完整性

4. 左右指针小结(基于课件内容)

  • 核心逻辑:通过 “两端收缩” 缩小查找范围,利用数组有序性或问题特性(如柱子高度对比)优化效率;
  • 关键注意事项:
    1. 适用前提:数组有序(如两数之和 II)或问题与两端状态直接相关(如盛水容器);
    2. 移动依据:明确 “移动哪个指针” 的判断条件,避免无效移动(如盛水容器需移动较矮柱子的指针)。

四、双指针整体总结(基于课件内容)

1. 两类双指针对比表

指针类型移动方向核心适用场景时间复杂度空间复杂度关键技巧课件对应段落
快慢指针同向链表环检测、中间节点、倒数第 K 节点O(n)O(1)控制指针速度差,制造相对距离
左右指针相向数组盛水、有序数组两数之和O(n)O(1)依据条件收缩两端范围,优化效率

2. 复习建议(结合课件备考需求)

  1. 抓核心逻辑:重点掌握快慢指针的 “速度差”、左右指针的 “两端收缩”,结合课件例题理解背后的设计思路(如盛水容器为何移动较矮指针);
  2. 练典型真题:优先练习课件提及的 LeetCode 题目(141、876、11、167),这些是 “传智杯” 初赛双指针题型的 “原型题”,竞赛常在此基础上变形;
  3. 强边界处理:始终关注指针越界问题(如快指针的None判断、数组指针的left < right循环条件),避免代码报错。
http://www.dtcms.com/a/430914.html

相关文章:

  • 模仿建设银行网站asp网站开发工具神器
  • C#基础06-函数异常
  • PostgreSQL LIMIT 语句详解
  • 网站开发是什么部门wordpress 缩略图清理
  • Kubernetes网络策略实战:精准控制frontend与backend跨-tail通信
  • 关于制作网站收费标准网站的结构类型
  • 【word解析】从OLE到OMML:公式格式转换的挑战与解决方案
  • 云梦网站开发如何做好企业网站
  • 常德网站制作公司多少钱服务器出租
  • Python 2025:低代码开发与自动化编程新纪元
  • wordpress手机端网站模板建站程序下载
  • SQL 多表查询常用语法速查:INNER JOIN / LEFT JOIN / RIGHT JOIN
  • p2p网贷网站开发页面设计简单吗
  • Java SE “异常处理 + IO + 序列化”面试清单(含超通俗生活案例与深度理解)
  • Redis 数据库管理与通信基础
  • GameObject 常见类型详解 -- 运输工具(TRANSPORT)
  • Spring的事务管理机制
  • DAY22 XML、XML解析
  • Lazygi - 让git操作不再困难
  • sns社交网站建设东莞服务36招
  • 有那些方法推广网站可用的在线网页代理
  • 一种基于模型残差的密度聚类方法之二(电力线分股)
  • 基于Keil下多文件打包生成LIB库的具体步骤
  • php网站开发教学购物软件哪个更好更便宜
  • 中小企业网站开发长期做网站应该购买稳定的空间
  • 二叉树的递归层序遍历
  • 牛客算法基础noob58 无限长正整数排列字符串
  • ECharts 配置语法详解
  • 哪个网站做自媒体比较好华为网站建设的目标是否明确
  • 【机器学习】 在Jupyter Notebook 中如何指定Python环境