力扣刷題筆記 167. 兩數之和 II - 輸入有序陣列
問題描述
給你一個下標從1開始的整數陣列numbers,該陣列已按非遞減順序排列,請你從陣列中找出滿足相加之和等於目標數 target 的兩個數。如果設這兩個數分別是 numbers[index1] 和 numbers[index2] ,則 1 <= index1 < index2 <= numbers.length 。
以長度為 2 的整數陣列 [index1, index2] 的形式返回這兩個整數的下標 index1 和 index2。
示例1:
輸入:numbers = [2,7,11,15], target = 9
輸出:[1,2]
解釋:2 與 7 之和等於目標數 9 。因此 index1 = 1, index2 = 2 。返回 [1, 2] 。
示例2:
輸入:numbers = [2,3,4], target = 6
輸出:[1,3]
解釋:2 與 4 之和等於目標數 6 。因此 index1 = 1, index2 = 3 。返回 [1, 3] 。
解題思路:
雙指標
由於需要尋找陣列中兩個元素相加之和等於target的元素下標。且陣列是非遞減排列的,因此可以考慮使用雙指標的方式。
解法1
left指標以陣列的第一個位置作為初始條件,right指標始終以left指標+1位置作為初始條件。先用left指標確定第一個元素,然後使用right指標尋找陣列中是否有和left指標對應元素相加等於target值的,如果當right指標和left指標的和大於target時,則證明陣列中沒有與left指標對應元素相加等於target的數,因此,將left指標右移。依此迴圈,上述過程如圖所示:
def twoSum(numbers, target): left = 0 length = len(numbers) while left <= length - 2: right = left + 1 while right < length: if numbers[left] + numbers[right] == target: return [left + 1, right + 1] elif numbers[left] + numbers[right] > target: break else: pre_right = numbers[right] while numbers[right] == pre_right and right < length - 1: right += 1 if right == length - 1: break if numbers[right] + numbers[left] == target: return [left + 1, right + 1] pre_left = numbers[left] while numbers[left] == pre_left: left += 1
解法2
left指標以陣列的第一個位置作為初始條件,right指標以陣列最後一個位置作為初始條件,left指標代表的是最小的元素值,right指標代表的是最大的元素值。若left指標對應的元素值和right指標對應的元素值相加小於target,則證明陣列中沒有與left指標對應元素相加等於target值得元素,left指標向右移。反之,若和大於target,則證明陣列中沒有與right值相加等於target值的元素,right右移。依此迴圈,上述過程如圖所示:
def twoSum2(numbers, target):
left = 0
right = len(numbers) - 1
while left <= right:
if numbers[left] + numbers[right] == target:
return [left + 1, right + 1]
elif numbers[left] + numbers[right] < target:
left += 1
else:
right -= 1
可以看出,第二種方法比第一種方法的效率要高很多
直接遍歷
依次遍歷陣列中的每個元素,判斷target-元素i的值在陣列中是否存在,若存在,則放回
def twoSum(numbers, target):
for i in range(len(numbers)):
if target-numbers[i] in numbers:
if numbers.index(target-numbers[i]) == i:
return [i+1,i+2]
return [i+1,numbers.index(target-numbers[i])+1]
break