题目描述
给你一个下标从 1 开始的整数数组 numbers,数组已按非递减顺序排列。请你从数组中找出满足相加之和等于目标数 target 的两个数。
返回值为长度为 2 的数组 [index1, index2],满足:
-
1 <= index1 < index2 <= numbers.length -
每个输入只对应唯一答案
-
不可重复使用相同元素
-
额外空间必须为常量级
示例
示例 1:
输入:numbers = [2,7,11,15], target = 9
输出:[1,2]
示例 2:
输入:numbers = [2,3,4], target = 6
输出:[1,3]
示例 3:
输入:numbers = [-1,0], target = -1
输出:[1,2]
解题思路
1️⃣ 双指针法(最优解)
由于数组已经有序,我们可以用双指针:
-
定义两个指针
left和right:-
left = 0(数组开头) -
right = numbersSize - 1(数组末尾)
-
-
计算当前和
sum = numbers[left] + numbers[right] -
根据 sum 与 target 比较:
-
sum == target→ 找到答案,返回[left+1, right+1] -
sum < target→ 左指针右移left++(增大 sum) -
sum > target→ 右指针左移right--(减小 sum)
-
这种方法只需常量额外空间,时间复杂度 O(n)。
2️⃣ 为什么一定正确?
-
数组有序 → 左指针增大,右指针减小
-
双指针会单调逼近 target,不会漏解
C语言实现
#include <stdio.h>
#include <stdlib.h>
int* twoSum(int* numbers, int numbersSize, int target, int* returnSize) {
int left = 0, right = numbersSize - 1;
int* res = (int*)malloc(sizeof(int) * 2);
*returnSize = 2;
while (left < right) {
int sum = numbers[left] + numbers[right];
if (sum == target) {
res[0] = left + 1; // 下标从1开始
res[1] = right + 1;
return res;
} else if (sum < target) {
left++;
} else {
right--;
}
}
return res; // 理论上不会走到这里
}
// 测试
int main() {
int numbers[] = {2,7,11,15};
int target = 9;
int returnSize;
int* res = twoSum(numbers, 4, target, &returnSize);
printf("[%d, %d]\n", res[0], res[1]);
free(res);
return 0;
}
输出:
[1, 2]
✅ 总结
-
题目关键在于数组已排序 → 可以使用双指针
-
双指针法:
-
左指针指向最小值
-
右指针指向最大值
-
根据 sum 与 target 比较调整指针
-
-
时间复杂度 O(n),空间复杂度 O(1)
-
面试高频考点:数组 + 双指针 + 常量空间