双指针法概述

适用场景判断使用双指针的典型信号:
题目要求 “原地修改”(不使用额外空间)
题目给出有序数组
要求保持 “相对顺序”
题目和两端比较有关

双指针分类

类型 核心思想 典型应用
对向指针 一个从左到右,一个从右到左,向中间移动 两数之和、盛最多水的容器、反转数组
快慢指针 fast 指针遍历数组,slow 指针记录有效位置 移除元素、删除链表重复节点、环形链表
左右指针 left 找最左,right 找最右,向中间逼近 二分查找变种、最长回文子串
单指针 遍历数组,在不额外空间下完成操作 简单原地修改场景

经典算法题:移动零(LeetCode 283)

题目描述:给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序,且必须原地修改数组。

示例:
输入:nums = [0, 1, 0, 3, 12]
输出:[1, 3, 12, 0, 0]

快慢指针解法(时间 O(n),空间 O(1))

核心思路:
slow 指针:记录下一个非零元素应该放置的位置
fast 指针:遍历整个数组,寻找非零元素
遇到非零元素时,将其赋值到 slow 位置,然后 slow 前进
遍历结束后,slow 之后的位置全部补 0

from typing import List

class Solution:
    def moveZeroes(self, nums: List[int]) -> None:
        """Do not return anything, modify nums in-place instead."""
        slow = 0  # 记录非零元素该放的位置
        # fast 指针遍历整个数组
        for fast in range(len(nums)):
            if nums[fast] != 0:  # 将非零元素移动到 slow 指针位置
                nums[slow] = nums[fast]
                slow += 1
        # 前面的非零元素已处理完,剩下的位置全部补 0
        for i in range(slow, len(nums)):
            nums[i] = 0

代码执行示例

nums = [2, 0, 3, 0, 9] 为例:
fast=0nums[0]=2≠0nums[0]=2slow=1
fast=1nums[1]=0 → 跳过
fast=2nums[2]=3≠0nums[1]=3slow=2
fast=3nums[3]=0 → 跳过
fast=4nums[4]=9≠0nums[2]=9slow=3
补零:nums[3] = 0nums[4] = 0
最终数组:[2, 3, 9, 0, 0]

双指针核心技巧总结

对向指针(左右指针)

初始化:left = 0right = len(nums) - 1
循环条件:while left <= right
移动逻辑:根据比较结果,让 left 右移或 right 左移,向中间逼近

快慢指针

初始化:slow = 0fast0 开始遍历
核心:fast 负责探索,slow 负责收集有效结果
典型操作:覆盖 / 交换,实现原地修改

指针操作本质

一次遍历:避免嵌套循环,时间复杂度优化到 O(n)
不额外数组:空间复杂度优化到 O(1)
整理结果:遍历完成后,对剩余位置做统一处理(如补零)

双指针适用场景速查

场景 指针类型 典型题目
原地修改数组 快慢指针 移动零、移除元素
有序数组找目标 对向指针 两数之和 II、三数之和
链表操作 快慢指针 环形链表、中间节点
字符串反转 对向指针 反转字符串、验证回文
Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐