Leetcode 167. 兩數之和 II - 輸入有序陣列 Java&Python
阿新 • • 發佈:2018-11-22
給定一個已按照升序排列 的有序陣列,找到兩個數使得它們相加之和等於目標數。
函式應該返回這兩個下標值 index1 和 index2,其中 index1 必須小於 index2。
說明:
- 返回的下標值(index1 和 index2)不是從零開始的。
- 你可以假設每個輸入只對應唯一的答案,而且你不可以重複使用相同的元素。
示例:
輸入: numbers = [2, 7, 11, 15], target = 9
輸出: [1,2]
解釋: 2 與 7 之和等於目標數 9 。因此 index1 = 1, index2 = 2 。
在這裡想和大家分享一下基本的解題思路,誠然這道題目非常簡單,但是當遇到難題的時候,一個好的解題思路或許會為我們找到突破點。這道題用暴力解法,兩次迴圈便可得出答案,但是提交給leetcode應該會timeout,因為O(n2)基本的演算法在資料量太大的時候,會非常耗時,那麼怎麼降低時間複雜度呢,結合題目,我們可以看到陣列是有序,既然是有序的陣列,是否可以用二分查詢來尋找target-number[i]呢?
public int[] twoSum(int[] numbers, int target) { int[] res = new int[2]; for (int i = 0; i < numbers.length; i++) { int pos = findIndex(numbers, i + 1, numbers.length - 1, target - numbers[i]); if (pos >= 0) { res[0] = i + 1; res[1] = pos + 1; } } return res; } private int findIndex(int[] numbers, int start, int end, int target) { while (start <= end) { int mid = start + (end - start) / 2; if (numbers[mid] == target) { return mid; } else if (numbers[mid] < target) { start = mid + 1; } else { end = mid - 1; } } return -1; }
這樣降到O(nlogn)便可以AC了,那麼還有更好的解決方案嗎,在遍歷一次的情況下,便可以得到結果,這裡可以使用對撞指標來解決,分別使兩個指標指向首尾,如果相加等於,便找到了對應的索引,如果小於需要右移左指標,大於便左移右指標。
public int[] twoSum(int[] numbers, int target) { int l = 0, 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 new int[2]; }
下面是Python實現
class Solution:
def twoSum(self, numbers, target):
"""
:type numbers: List[int]
:type target: int
:rtype: List[int]
"""
i = 0
j = len(numbers) - 1
while i < j:
if numbers[i] + numbers[j] == target:
return [i + 1, j + 1]
elif numbers[i] + numbers[j] < target:
i += 1
else:
j -= 1
關於對撞指標,類似的題目還有Leetcode125號問題:驗證迴文串, 345號問題 反轉字串中的母音字母等,有興趣的同學也可以做做這些題目。