在刷 LeetCode 的过程中,“双指针”几乎是算法题里使用频率最高的技巧之一。

今天我们就通过两道经典题目,彻底掌握双指针思想:

  1. 283. 移动零 Move Zeroes

  2. 11. 盛最多水的容器 Container With Most Water

一、283. 移动零(Move Zeroes)

题目描述

给定一个数组 nums,将所有的 0 移动到数组末尾,同时保持非零元素的相对顺序。

必须在 原数组上操作(in-place),不能使用额外的数组空间。

解法一:两次遍历(好理解)

步骤:

  1. 把所有非零按顺序放到数组前部

  2. 把剩下的位置全部填 0

代码:

int slow = 0;
for (int x : nums)
    if (x != 0) nums[slow++] = x;

while (slow < nums.size())
    nums[slow++] = 0;

虽然简单,但需要遍历两次。

解法二:双指针,一次遍历(最推荐)

简化版思路如下:

  • 慢指针 slow 指向下一个“应该放非零元素”的位置

  • 快指针 fast 负责遍历数组

  • fast 遇到非零 → 与 slow 交换 → slow++

  • fast 遇到 0 → 不做任何事,因为 slow 指向的是“应该被覆盖的位置”

👉 为什么交换后 slow 仍然指向空位?

因为:

  • slow 之前一定是 0(否则它早就被覆盖了)

  • fast 遇到非 0,把它交换到 slow 的位置

  • fast 所在位置被换成 0

  • 所以 slow++ 后新的 slow 依然指向 “未处理的位置”,保持空位含义

代码:

class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        // 思路: 本质就是双指针,慢指针拿来指向0,快指针往前走进行遍历,快指针遇到非0就交换,确保0往后移动。
        int slow = 0;
        for (int& fast : nums) {
            if (fast) {
                swap(fast, nums[slow]);
                slow++;
            }
        }
    }
};

时间复杂度

  • O(n) 遍历一次

  • 交换次数 ≤ 非零个数

空间复杂度

  • O(1)

二、11. 盛最多水的容器(Container With Most Water)

题目描述

给定 height[i] 表示墙的高度,左右两堵墙与 x 轴围成的容器容量为:

面积 = min(height[left], height[right]) * (right - left)

要求求最大容量。


核心思路:双指针夹逼

初始:

  • left = 0

  • right = n - 1

每次计算当前面积后:

  • 移动较矮的那根柱子
    因为:

容量 = 宽度 * 较矮高度
宽度必然随着移动变小,所以想要变大只能通过变高
→ 必须移动较矮端,才可能获得更高的边界

否则移动高的那一边一点意义都没有。


✔ 正确代码

class Solution {
public:
    int maxArea(vector<int>& height) {
        // 思路: 双指针进行遍历,同时维护最大值,高度小的那个是限制条件,把它移动
        int ans = 0;
        int left = 0;
        int right = height.size() - 1;
        while(left < right) {
            int area = (right - left) * min(height[left], height[right]);
            ans = max(ans, area);
            if (height[left] < height[right]) {
                left++;
            }
            else right--;
        }
        return ans;
    }
};

时间复杂度

  • O(n)。每根柱子最多被操作一次。

空间复杂度

  • O(1),只用几个变量。

总结

题目技巧核心思路
Move Zeroes双指针(快慢指针)fast 遇到非零就交换到 slow 位置,slow 始终指向下一个“空位”
盛最多水的容器双指针(夹逼)宽度缩小不可避免,必须移动较矮侧来尝试增大高度

双指针本质上就是:

用两个指针在数组上“控制局面”

  • 一个负责位置

  • 一个负责遍历

  • 或者两个同时移动,缩小范围

只要理解了这种思想,很多题会变得非常简单。

更多推荐