167. 两数之和 II - 输入有序数组
✨核心逻辑
本题由于数组已经是按 非递减顺序 排列的,因此可以利用 双指针(对撞指针) 策略在 O(1) 的额外空间内高效解决:
- 初始化指针:左指针
left指向数组的最左端(最小值),右指针right指向数组的最右端(最大值)。 - 计算与比较:计算当前两个指针指向元素的和
result。 - 移动指针:
- 如果
result == target,说明找到了正确答案,直接跳出循环。 - 如果
result > target,说明两数之和太大了,需要减小,因此将右指针right向左移动一位。 - 如果
result < target,说明两数之和太小了,需要增大,因此将左指针left向右移动一位。
- 如果
- 返回结果:题目要求下标从
1开始计算,因此在最终返回时需要将索引+1。
🔥代码实现(含详细变量注释)
class Solution {
public int[] twoSum(int[] numbers, int target) {
// left:左指针,初始指向数组的第一个元素(索引为 0)
int left = 0;
// right:右指针,初始指向数组的最后一个元素(索引为 numbers.length - 1)
int right = numbers.length - 1;
// 当左指针小于右指针时,继续循环查找
while (left < right) {
// result:暂存当前左右指针指向元素的和
int result = numbers[left] + numbers[right];
// 如果两数之和正好等于目标值,说明找到了答案,跳出循环
if (result == target) {
break;
} else if (result > target) {
// 如果两数之和大于目标值,说明当前右边的数太大
// 需要将右指针向左移动,以减小两数之和
right--;
} else {
// 如果两数之和小于目标值,说明当前左边的数太小
// 需要将左指针向右移动,以增大两数之和
left++;
}
}
// 根据题目要求(下标从 1 开始),返回时索引各自加 1
return new int[]{left + 1, right + 1};
}
}
- ⏱️复杂度分析
时间复杂度:O(N),其中 N 是数组的长度。左指针 left 和右指针 right 最多遍历整个数组一次,循环内部只执行常数次的操作。
空间复杂度:O(1),只使用了 left、right 和 result 三个额外的整型变量,没有占用额外的数组空间。
🔍总结一下:
思路没有往双指针上靠拢,因此总结几点:

.