[ 题目描述 ]:
[ 思路 ]:
- 题目要求求数值numbers中的和为 target 的两个数的下标
- 最简单的思路就是暴力求解,两两挨个组合,但时间复杂度为O(n2),不一定能通过
- 因为数组为非递减,那我们可以使用双指针,并从数组首尾出发
- 如果 和 > target,则右指针向左移动,因为左边的数小于右边
- 如果 和 < target,则左指针向右移动,因为右边的数大于左边
- 运行如下
int* twoSum(int* numbers, int numbersSize, int target, int* returnSize) {int left=0,right=numbersSize-1;int* ans=(int*)malloc(sizeof(int)*2);*returnSize=2;while(left<right){if(numbers[left]+numbers[right]==target){ans[0]=left+1;ans[1]=right+1;break;}else if(numbers[left]+numbers[right]>target){right--;}else{left++;} }return ans;
}
- 时间复杂度O(n),空间复杂度O(1)
[ 官方题解 ]:
- 一、二分查找,在数组中找到两个数,使得它们的和等于目标值,可以首先固定第一个数,然后寻找第二个数,第二个数等于目标值减去第一个数的差。利用数组的有序性质,可以通过二分查找的方法寻找第二个数。为了避免重复寻找,在寻找第二个数时,只在第一个数的右侧寻找。
int* twoSum(int* numbers, int numbersSize, int target, int* returnSize) {int* ret = (int*)malloc(sizeof(int) * 2);*returnSize = 2;for (int i = 0; i < numbersSize; ++i) {int low = i + 1, high = numbersSize - 1;while (low <= high) {int mid = (high - low) / 2 + low;if (numbers[mid] == target - numbers[i]) {ret[0] = i + 1, ret[1] = mid + 1;return ret;} else if (numbers[mid] > target - numbers[i]) {high = mid - 1;} else {low = mid + 1;}}}ret[0] = -1, ret[1] = -1;return ret;
}
- 二、双指针,如上