【用双指针解决有序数组问题】搞定“两数之和 II”与“移动零”!(JS + Python 双解)

89 阅读3分钟

🧠 引言

你是否遇到过这类问题:

  • 数组已排序,找出一对数使其和为目标值?
  • 如何就地移动数组中的零,让非零元素排前面?

这些问题的高效解法,离不开“双指针”技巧

本篇带你通过两个经典例题——

  1. Two Sum II(有序数组两数之和)
  2. 移动零(in-place)

全面掌握双指针的使用套路与边界细节,并配备 JavaScript + Python 双解法!


🧱 一、什么是双指针?

双指针就是同时使用两个指针(索引)来控制数组的处理位置,常用于有序数组、反转、滑动窗口优化等场景

常见类型:

类型应用场景
对撞指针从两端向中间靠拢
快慢指针检测循环/过滤元素/合并等

🧪 Part 1:两数之和 II(LeetCode 167)

❓题目描述

给定一个有序数组 numbers 和一个目标值 target,返回两个数的下标(从1开始) ,使它们的和为目标值。

输入: numbers = [2,7,11,15], target = 9
输出: [1,2]

✅ 解法思路(对撞指针)

  • 设置 left = 0right = n - 1
  • sum < target,左指针右移
  • sum > target,右指针左移
  • 相等则找到!

💻 JavaScript 实现

function twoSum(numbers, target) {
  let left = 0, right = numbers.length - 1;

  while (left < right) {
    const sum = numbers[left] + numbers[right];
    if (sum === target) return [left + 1, right + 1];
    else if (sum < target) left++;
    else right--;
  }
  return [];
}

🐍 Python 实现

def two_sum(numbers, target):
    left, right = 0, len(numbers) - 1

    while left < right:
        total = numbers[left] + numbers[right]
        if total == target:
            return [left + 1, right + 1]
        elif total < target:
            left += 1
        else:
            right -= 1
    return []

🧪 Part 2:移动零(LeetCode 283)

❓题目描述

给定一个数组 nums,将所有 0 移动到末尾,同时保持非零元素的相对顺序不变。必须原地操作。

输入: [0,1,0,3,12]
输出: [1,3,12,0,0]

✅ 解法思路(快慢指针)

  • 使用 slow 记录非零元素下一个要填的位置
  • 使用 fast 遍历数组,将非零元素拷贝到 slow
  • 最后将剩余部分置为 0

💻 JavaScript 实现

function moveZeroes(nums) {
  let slow = 0;
  for (let fast = 0; fast < nums.length; fast++) {
    if (nums[fast] !== 0) {
      nums[slow++] = nums[fast];
    }
  }
  while (slow < nums.length) {
    nums[slow++] = 0;
  }
  return nums;
}

// 示例
console.log(moveZeroes([0,1,0,3,12])); // [1,3,12,0,0]

🐍 Python 实现

def move_zeroes(nums):
    slow = 0
    for fast in range(len(nums)):
        if nums[fast] != 0:
            nums[slow] = nums[fast]
            slow += 1

    for i in range(slow, len(nums)):
        nums[i] = 0

    return nums

# 示例
print(move_zeroes([0, 1, 0, 3, 12]))  # [1, 3, 12, 0, 0]

⚠️ 易错点提醒

错误点正确写法
忘记处理末尾 0 填充最后用 while 或 for 补 0
slowfast 写反fast 遍历找数,slow 移动非 0
双指针条件写错left < right 是最常见的边界形式

🧩 拓展任务

  • 支持“多指针同步扫描”场景(如归并)
  • 用双指针实现字符串回文判断
  • 用双指针处理“最长不重复子串”问题

📚 总结一句话

双指针 = 空间压缩神器 + 性能优化利器,尤其在数组和字符串场景中堪称王炸!


📘 下一篇预告:

第13篇:【前端也要懂并查集?】JS 与 Python 解“朋友圈”和“岛屿数量”!