PHP双指针算法是面试中高频出现的考察点,核心思想是通过两个指针在数据结构上按照特定规则移动,减少不必要的遍历次数,从而优化算法的时间复杂度,很多数组和字符串相关的面试题都可以用双指针思路解决。

什么是双指针算法
双指针算法指的是在遍历数据结构时,同时使用两个指针(可以是数组下标、对象引用等)来标记位置,两个指针根据问题需求同步或异步移动,避免多层嵌套循环,通常能把时间复杂度从O(n²)降到O(n)。在PHP中,双指针常用于数组、字符串的处理场景。
面试常见双指针问题及实现
1. 有序数组两数之和
题目:给定一个升序排列的数组和一个目标值,找出数组中和为目标值的两个数,返回它们的下标。要求时间复杂度O(n),空间复杂度O(1)。
思路:左指针指向数组开头,右指针指向数组末尾,计算两数之和,如果等于目标值就返回,小于目标值就左指针右移,大于目标值就右指针左移,直到两指针相遇。
<?php
function twoSumSorted($arr, $target) {
$left = 0;
$right = count($arr) - 1;
while ($left < $right) {
$sum = $arr[$left] + $arr[$right];
if ($sum == $target) {
return [$left, $right];
} elseif ($sum < $target) {
$left++;
} else {
$right--;
}
}
return []; // 没有找到符合条件的两个数
}
// 测试示例
$testArr = [1, 2, 3, 4, 6, 8];
$result = twoSumSorted($testArr, 7);
print_r($result); // 输出 Array ( [0] => 1 [1] => 4 )
?>
2. 数组去重(保留有序)
题目:给定一个可能包含重复元素的数组,原地去除重复元素,使每个元素只出现一次,返回去重后数组的新长度,要求空间复杂度O(1)。
思路:慢指针指向当前有效去重元素的末尾,快指针遍历数组,当快指针指向的元素和慢指针指向的元素不同时,慢指针右移一位,然后把快指针的元素赋值给慢指针的位置。
<?php
function removeDuplicates(&$arr) {
if (empty($arr)) {
return 0;
}
$slow = 0;
for ($fast = 1; $fast < count($arr); $fast++) {
if ($arr[$fast] != $arr[$slow]) {
$slow++;
$arr[$slow] = $arr[$fast];
}
}
return $slow + 1;
}
// 测试示例
$testArr = [1, 1, 2, 3, 3, 4, 4, 5];
$len = removeDuplicates($testArr);
echo "去重后长度:" . $len . "n"; // 输出 5
print_r(array_slice($testArr, 0, $len)); // 输出 Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 )
?>
3. 反转字符串
题目:给定一个字符串,原地反转字符串的内容,要求时间复杂度O(n),空间复杂度O(1)。
思路:左指针指向字符串开头,右指针指向字符串末尾,交换两个指针指向的字符,然后左指针右移,右指针左移,直到两指针相遇。
<?php
function reverseString(&$str) {
$left = 0;
$right = strlen($str) - 1;
while ($left < $right) {
$temp = $str[$left];
$str[$left] = $str[$right];
$str[$right] = $temp;
$left++;
$right--;
}
}
// 测试示例
$testStr = "hello";
reverseString($testStr);
echo $testStr; // 输出 olleh
?>
面试注意事项
面试中遇到双指针相关问题时,首先要先明确数据结构的特征,比如数组是否有序、是否需要原地修改等,再确定指针的移动规则。写代码前可以先和面试官说明思路,确认无误再动手。另外要注意边界条件的处理,比如空数组、数组只有一个元素的情况,避免出现数组下标越界的错误。
双指针算法的核心不是记住固定写法,而是理解两个指针协同移动减少遍历次数的思想,很多变体题都可以基于这个核心思路推导出来,面试时遇到陌生题也可以尝试往双指针方向思考。