力扣刷題筆記:167.兩數之和 II - 輸入有序陣列(二分法+雙指標法,雙指標法更快,程式碼很好理解)
題目:
167、兩數之和 II - 輸入有序陣列
給定一個已按照 升序排列 的整數陣列 numbers ,請你從陣列中找出兩個數滿足相加之和等於目標數 target 。
函式應該以長度為 2 的整數陣列的形式返回這兩個數的下標值。numbers 的下標 從 1 開始計數 ,所以答案陣列應當滿足 1 <= answer[0] < answer[1] <= numbers.length 。
你可以假設每個輸入只對應唯一的答案,而且你不可以重複使用相同的元素。
示例 1:
輸入:numbers = [2,7,11,15], target = 9
輸出:[1,2]
解釋:2 與 7 之和等於目標數 9 。因此 index1 = 1, index2 = 2 。
示例 2:
輸入:numbers = [2,3,4], target = 6
輸出:[1,3]
示例 3:
輸入:numbers = [-1,0], target = -1
輸出:[1,2]
提示:
2 <= numbers.length <= 3 * 10^4
-1000 <= numbers[i] <= 1000
numbers 按 遞增順序 排列
-1000 <= target <= 1000
僅存在一個有效答案
題解思路:
一、二分查詢法思路:
在陣列中找到兩個數,使得它們的和等於目標值,可以首先固定第一個數,然後尋找第二個數,第二個數等於目標值減去第一個數的差。利用陣列的有序性質,可以通過二分查詢的方法尋找第二個數。為了避免重複尋找,在尋找第二個數時,只在第一個數的右側尋找。寫法直接按照二分查詢模板寫即可。
時間複雜度O(nlog(n))
題解python程式碼:
# 二分查詢法
class Solution:
def twoSum(self, numbers: List[int], target: int) -> List[int]:
n = len(numbers)
for i in range(n-1):
left, right = i+1, n-1 #標準二分查詢模板寫法
while left<=right:
mid = (left+right)//2
if numbers[mid]==target-numbers[i]:
return [i+1, mid+1]
if numbers[mid]>target-numbers[i]:
right = mid-1
else:
left = mid+1
return [-1, -1]
二、雙指標法思路:
針對題目所給陣列,定義頭尾兩個指標,在整個移動過程中,左指標不可能移到 ii 的右側,右指標不可能移到 jj 的左側,因此不會把可能的解過濾掉。
指標移動時,比較左右指標所指值之和與target的大小,等於則直接返回答案,小則左指標往右移動,大則右指標往左移動。
由於題目確保有唯一的答案,因此使用雙指標一定可以找到答案。
時間複雜度O(n)
題解python程式碼:
# 雙指標法
class Solution:
def twoSum(self, numbers: List[int], target: int) -> List[int]:
n = len(numbers)
left, right = 0, n-1
while left<=right:
total = numbers[left]+numbers[right]
if total==target:
return [left+1, right+1]
elif total<target:
left += 1
else:
right -= 1
return [-1, -1]
作者:a-qing-ge
連結:https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted/solution/yi-er-fen-cha-zhao-fa-shi-jian-fu-za-du-po65c/
來源:力扣(LeetCode)https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted/