Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
Example:
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
此題要求從一個數字陣列中取出其中兩個數字,這兩個數字的和剛好等於指定的值(target)。
若採用雙迴圈暴力法依序從第一個數字判斷與其他數字加總是否符合,則時間複雜度為O(N²)。
倘若陣列是已經排序過的,則可以使用雙指針法(Two Pointer)來解,即使用兩個指針分別指向陣列的兩端,例如若陣列為升冪排序,兩指針所指向的值其和大於所求的值,則將右指針的位置向左移動,若兩指針所指向的值小於所求的值,則將左指針的位置向右移動,直到其和等於所求之值或左指針與右指針指到同一個位置(因為題目規定必須返回兩個不同的索引)。
更好的方法是使用Hash Table來降低時間複雜度到O(N),具體做法為依序從第一個數字(nums[i])開始,算出目標值(target)減去該數字所得到的差值(target-num[i]),查看該差值是否存在於HashMap裡,若不存在,則將該差值及其索引存進HashTable;若存在,則回傳當下數字(nums[i])及差值(target-nums[i])的索引。
時間複雜度:O(N^2)
空間複雜度:O(N)
public int[] twoSum(int[] nums, int target) {
for (int i = 0; i < nums.length; i++) {
for (int j = i + 1; j < nums.length; j++) {
if (nums[j] == target - nums[i]) {
return new int[] { i, j };
}
}
}
throw new IllegalArgumentException("No two sum solution");
}
時間複雜度:O(N)
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
x = 0
y = len(nums) - 1
while x < y:
if nums[x] + nums[y] == target:
return [x, y]
elif nums[x] + nums[y] > target:
y-=1
else:
x+=1
時間複雜度:O(N)
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
dic ={}
for i,v in enumerate(nums):
if target-v in dic:
return [dic[target-v], i]
dic[v] = i
此題重點在於能想到使用HashTable使時間複雜度最小化,因此要能夠理解Array及HashTable/Dictionary在搜尋上的時間複雜度差異,以及HashTable/Dictionary的使用語法。
希望透過記錄解題的過程,可以對於資料結構及演算法等有更深一層的想法。
如有需訂正的地方歡迎告知,若有更好的解法也歡迎留言,謝謝。