https://leetcode.com/problems/two-sum-ii-input-array-is-sorted/
给定一个已经排好升序的数组和一个target值,查找和为target的两个元素,并返回它们的下标+1组成的长度为2的数组。注意,index1必须小于index2。
一、问题分析
测试用例:
Input: numbers = [2,7,11,15], target = 9
Output: [1,2]
Explanation: The sum of 2 and 7 is 9. Therefore index1 = 1, index2 = 2.
注意到返回的数组的元素表示的是该两个元素是第几个,不是下标。
这道题使用双重循环的暴力法即可解决,不过由于这里是有序,所以可以使用二分查找法。先遍历数组的每一个元素numbers[i],如果它是答案中的一员,那么target - numbers[i]肯定也存在数组中。我们只需要二分查找是否存在值为target - numbers[i]的元素即可。
由于题目要求index1必须小于index2。所以我们可以从0开始往右边遍历,然后二分查找的范围为[i+1, number.length-1]。
二、代码实现
class Solution {
public int[] twoSum(int[] numbers, int target) {
if (numbers == null || numbers.length == 0) {
return null;
}
for (int i = 0; i<numbers.length; i++) {
int newTarget = target - numbers[i];
int index = binarySearch(numbers, i+1, numbers.length - 1, newTarget);
if (index == -1) {
continue;
}
return new int[] {i + 1, index + 1};
}
return null;
}
public int binarySearch(int[] numbers, int left, int right, int target) {
if (left > right) {
return -1;
}
while (left < right) {
int mid = left + (right - left) / 2;
if (numbers[mid] >= target) {
right = mid;
} else {
left = mid + 1;
}
}
if (numbers[left] == target) {
return left;
}
return -1;
}
}
更好的实现方式(使用双指针法):
class Solution {
public int[] twoSum(int[] numbers, int target) {
int i = 0, j = numbers.length - 1;
int sum = numbers[i] + numbers[j];
while (sum != target) {
if (sum < target) {
i++;
} else {
j--;
}
sum = numbers[i] + numbers[j];
}
return new int[] {i+1, j+1};
}
}
当然也可以这么写
class Solution {
public int[] twoSum(int[] numbers, int target) {
int i = 0, j = numbers.length - 1;
while (i < j) {
int sum = numbers[i] + numbers[j];
if (sum == target) {
return new int[] {i + 1, j + 1};
} else if (sum < target) {
i++;
} else {
j--;
}
}
//永远不会执行这里,因为给的所有测试用例都是有符合的答案的
return new int[] {-1, -1};
}
}