版权声明:本文为博主原创文章,转载请注明出处 https://blog.csdn.net/love905661433/article/details/83657039
题目
给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。
函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。
说明:
返回的下标值(index1 和 index2)不是从零开始的。
你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。
示例:
输入: numbers = [2, 7, 11, 15], target = 9
输出: [1,2]
解释: 2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。
解题
方法一 : 二分查找
因为数组是有序的, 所以可以使用二分查找的方式解决, 遍历数组, 在遍历i元素时, 在[i + 1…nums.length - 1]的区间查找等于target - nums[i]的元素, 代码如下:
class Solution {
// 二分查找, 在numbers[l..r]的区间查找值为target的元素, 返回下标索引, 找不到符合条件的元素返回-1
private int bs(int[] numbers, int target, int l, int r){
if(l > r){
return -1;
}
if(l == r){
if(numbers[l] == target){
return r;
} else {
return -1;
}
}
int mid = (r - l ) / 2 + l;
if(target == numbers[mid]){
return mid;
} else if (target < numbers[mid]){
return bs(numbers, target, l, mid - 1);
} else {
return bs(numbers, target, mid + 1, r);
}
}
public int[] twoSum(int[] numbers, int target) {
int[] indexs = new int[2];
for(int i = 0; i < numbers.length; i++){
int tempTarget = target - numbers[i];
int secondIndex = bs(numbers, tempTarget, i + 1, numbers.length - 1);
if(secondIndex != -1){
// 下标从1开始, 所以数组下标都要加上1
indexs[0] = i + 1;
indexs[1] = secondIndex + 1;
break;
}
}
return indexs;
}
}
方法二 : 双指针
- 使用两个变量l,r分别指向数组的两侧, 初始化l = 0, r = nums.length -1
- 如果nums[l] + nums[r] == target就表示找到这两个和为target的两个数字了
- 如果nums[l] + nums[r] < target就表示l小了 , l++即可
- 如果nums[l] + nums[r] > target就表示r打了, r–即可
- 以上条件都是基于数组有序的情况下才成立, 刚好本题数组就是有序的, 代码如下:
class Solution {
public int[] twoSum(int[] numbers, int target) {
int l = 0;
int r = numbers.length - 1;
while(l < r){
if(numbers[l] + numbers[r] == target){
return new int[]{l + 1, r + 1};
} else if(numbers[l] + numbers[r] < target){
l ++;
} else{
r --;
}
}
return null;
}
}
双指针的时间复杂度是O(logn), 高于二分查找