📖 双指针专题怎么用?

双指针是面试出场率最高的技巧——两个指针从两端、或快慢不同速度遍历,把 O(n²) 降到 O(n)。

本专题包含 4 道题,都是外企面试高频真题。每道题按统一结构讲解:

复习建议:先看生活类比理解问题本质,再看思路建立解题框架,最后手写代码 3 遍形成肌肉记忆。面试时先口述思路,确认无误后再写代码。

1回文检测 (Valid Palindrome) Easy

题目(人话版)

判断一个字符串是不是"回文"——正着读和倒着读一样。比如 "racecar" 正着读和倒着读都是 "racecar",是回文。"hello" 倒过来是 "olleh",不是。

💡 生活类比:回文就像镜像对称——你拿一面镜子放在字符串中间,左右两边完全对称。就像一些城市的设计:左边有个公园,右边也有个一模一样的公园。

方法一:翻转比较法(最直觉)

把字符串翻转过来,和原字符串比较——一样就是回文。一行代码搞定。

palindrome.js
1
2
3
function isPalindrome(s) { return s === s.split('').reverse().join(''); } // "racecar" → split → ['r','a','c','e','c','a','r'] // → reverse → ['r','a','c','e','c','a','r'] (不变!) // → join → "racecar" ✓

简单粗暴,但创建了新数组,空间 O(n)。

方法二:双指针法(面试标准答案)

第一步:左右指针指向两端 r a c e c a r ← left right → r === r ✓ 一起往中间走 第二步:指针向中间移动,继续比较 r a c e c a r
双指针法:左右两个指针从两端向中间走,每次比较指向的字符是否相同
palindrome-pointers.js
1
2
3
4
5
6
7
8
9
function isPalindrome(s) { let left = 0; let right = s.length - 1; while (left < right) { if (s[left] !== s[right]) { return false; // 不一样就不是回文 } left++; // 左指针往右走 right--; // 右指针往左走 } return true; // 全部比完了,都一样 }
方法时间空间特点
翻转比较O(n)O(n)一行代码,但用了额外空间
双指针O(n)O(1)✅ 不用额外空间,面试首选
面试变体:面试官会说"如果字符串里有空格和标点呢?比如 'A man, a plan, a canal: Panama'"。解法:先过滤掉非字母数字、转小写,再用双指针。

2反转字符串 (Reverse String) Easy

题目(人话版)

['h','e','l','l','o'] 反转成 ['o','l','l','e','h']。要求原地修改,不能用额外数组。

💡 生活类比:就像排队时让队伍掉个头——最左边的人和最右边的人交换位置,然后第二左和第二右交换……一直交换到中间。

思路:双指针交换

第一步:交换 h 和 o h e l l l o 交换 交换后:[o, e, l, l, h] → 指针向中间移动 o e l l h h
双指针从两端向中间走,每次交换两个指针指向的元素
reverseString.js
1
2
3
4
5
6
7
8
9
function reverseString(s) { let left = 0; let right = s.length - 1; while (left < right) { // ES6 解构赋值交换两个元素(一行搞定!) [s[left], s[right]] = [s[right], s[left]]; left++; right--; } } // 其他一行写法(面试官追问"你知道几种?"): // s.reverse() ← 最简单,但面试要你说原理

时间 O(n),空间 O(1)。原地修改,不需要额外数组。

面试加分项:主动说"除了双指针,JS 还有 s.reverse()s.split('').reverse().join('') 两种写法,但 reverse() 会修改原数组,面试要求原地修改时正好用它。双指针的好处是可以在任何语言通用——C/Java/Python 都能写。"

3合并两个有序数组 (Merge Sorted Arrays) Easy

题目(人话版)

给你两个已经排好序的数组 [1,3,5][2,4,6],合并成一个有序数组 [1,2,3,4,5,6]

💡 生活类比:就像两列已经按身高排好的队伍,要合成一列还是按身高排。你不需要把所有人混在一起重新排——只需要看两队最前面的人谁矮,谁矮谁先出来站到新队伍里。这就是"归并"思想。

思路:双指针

两队指针各自从最前面开始,谁小谁先进新数组 A队: 1 3 5 B队: 2 4 6 1 < 2 A的1先进! 结果: [1, _, _, _, _, _]
比较两队最前面的元素,小的先进结果数组
mergeSorted.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function merge(nums1, nums2) { const result = []; let i = 0, j = 0; // 两队都还有人的时候,比谁的小 while (i < nums1.length && j < nums2.length) { if (nums1[i] <= nums2[j]) { result.push(nums1[i++]); } else { result.push(nums2[j++]); } } // 其中一队走完了,把另一队剩余的都加进去 while (i < nums1.length) result.push(nums1[i++]); while (j < nums2.length) result.push(nums2[j++]); return result; }

时间 O(n+m),空间 O(n+m)。两个数组各走一遍,不会回头。

别忘收尾!while 循环结束后,一定有一队还剩人没进结果数组。两个 while 收尾就是把剩下的全推进去。漏掉这个是初学者最常见的 bug。

4移动零 (Move Zeroes) Easy

题目(人话版)

把数组里所有的 0 移到末尾,其他数字保持原来的顺序。[0,1,0,3,12][1,3,12,0,0]。要求原地修改

💡 生活类比:想象一排人站着,其中一些人没来(空位=0)。你要让所有来了的人往前挪,空位都留到最后。快慢指针就像:一个人负责"往后找下一个来了的人"(快指针),另一个人负责"站在下一个该填的位置等着"(慢指针)。

思路:快慢双指针

慢指针指向"下一个非零数应该放的位置",快指针负责扫描整个数组。

快指针扫描,遇到非零就和慢指针交换 0 1 0 3 12 slow↑ fast↑(非零!交换) 结果:[1,0,0,3,12] → slow到了1,继续扫
moveZeroes.js
1
2
3
4
5
6
7
8
9
10
function moveZeroes(nums) { let slow = 0; // 下一个非零数该放的位置 for (let fast = 0; fast < nums.length; fast++) { if (nums[fast] !== 0) { // 快指针遇到非零,和慢指针交换 [nums[slow], nums[fast]] = [nums[fast], nums[slow]]; slow++; // 慢指针往前走一格 } } } // [0,1,0,3,12] → [1,0,0,3,12] → [1,3,0,0,12] → [1,3,12,0,0]

时间 O(n),空间 O(1)。一次遍历搞定。

面试加分:主动说"也可以先统计 0 的个数,然后把非零数覆盖到前面,最后补 0。但双指针交换法更优雅,一次遍历就完成。"

📋 双指针专题速查表

#题目难度
1回文检测 (Valid Palindrome)Easy
2反转字符串 (Reverse String)Easy
3合并两个有序数组 (Merge Sorted Arrays)Easy
4移动零 (Move Zeroes)Easy
考点核心:双指针专题的核心就是"用对工具,降复杂度"。 面试时拿到题先想:"这道题能用双指针吗?" 如果能,先说思路再写代码,面试官就知道你的分析能力。

🔗 其他考点专题

哈希表专题:两数之和 (Two Sum), 有效的字母异位词 (Valid Anagram), 数组去重/判断有重复 (Contains Duplicate), 第一个唯一字符 (First Unique Character)

动态规划专题:斐波那契数列 (Fibonacci), 爬楼梯 (Climbing Stairs), 最大子序和 (Max Subarray)

位运算专题:只出现一次的数字 (Single Number), 缺失数字 (Missing Number)

栈与滑动窗口专题:有效括号 (Valid Parentheses), 最长不重复子串 (Longest Substring)

综合技巧专题:FizzBuzz, 买卖股票的最佳时机 (Best Time to Buy/Sell Stock), 多数元素 (Majority Element), 旋转数组 (Rotate Array), 二分查找 (Binary Search)

← 返回图解算法与模式