167.两数之和II-输入有序数组
题目描述
1.双指针法
我们可以观察原数组得到(这里建议大家画图看看,真的非常清晰),因为题目一定有解,解唯一且数组按升序排列,所以我们不妨让left
指针指向数组中未访问过的最小值(即从numbers[0]开始向右移动);让right
指针指向数组中未访问过的最大值(即从numbers[n-1]开始向左移动)。
若此时numbers[left]+numbers[right]>target
,则将right
指针向左移动right--
(即用第二大的数与最小数相加试试),同理若numbers[left]+numbers[right]<target
,则将left
指针向右移动left++
(即用稍微大一点的数相加试试);以此类推直到numbers[left]+numbers[right]==target
。
注意:题目要求结果下标从1开始计数,所以应将最终 right 和 left 加1存入新数组得到最终结果。
public int[] twoSum(int[] numbers, int target) {
int left=0;
int n=numbers.length;
int right=n-1;
while(left<right){
if((numbers[left]+numbers[right])>target){
right--;
}else if(numbers[left]+numbers[right]<target){
left++;
}else{
break;
}
}
int[] newArr=new int[]{left+1,right+1};
return newArr;
}
2.二分查找法
利用数组的有序性质,可以使用二分查找的方法。即确定一个数(先从numbers[0]作为第一个确定的数,若i=0的一次for循环执行结束没有得到结果,执行i++,将numbers[1]作为第一个确定的数继续循环直到得到正确结果),然后通过二分查找int mid = (high - low) / 2 + low
,判断numbers[mid] == target - numbers[i]
是否成立;若numbers[mid] > target - numbers[i]
则右指针向 high =mid-1,若numbers[mid] < target - numbers[i]
则左指针low = mid+1;直至 low>right 结束此次对于第二个数的查找,若没有得到结果则说明第一个数不对,改变第一个数值继续执行二分查找第二个数;循环至获得最终结果。
public int[] twoSum(int[] numbers, int target) {
for (int i = 0; i < numbers.length; i++) {
int low = i + 1, high = numbers.length - 1;
while (low <= high) {
int mid = (high - low) / 2 + low; //防止超过int范围
if (numbers[mid] == target - numbers[i]) {
return new int[]{i + 1, mid + 1};
} else if (numbers[mid] > target - numbers[i]) {
high = mid - 1;
} else {
low = mid + 1;
}
}
}
}