LeetCode-167. 兩數之和 II - 輸入有序陣列
阿新 • • 發佈:2018-11-24
題目
給定一個已按照升序排列 的有序陣列,找到兩個數使得它們相加之和等於目標數。
函式應該返回這兩個下標值 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), 高於二分查詢