[LeetCode]1.TwoSum(Python實現)
1.題目描述
給定一個整數陣列和一個目標值,找出陣列中和為目標值的兩個數。
你可以假設每個輸入只對應一種答案,且同樣的元素不能被重複利用
- 示例:
給定 nums = [2, 7, 11, 15], target = 9
因為 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
2.程式碼實現
1. 方法一:
[分析]:
自然而然的想法,首先用for迴圈對nums陣列進行遍歷,從第一個元素開始,然後再查詢陣列中有沒有target-nums[i]這個元素;有的話,則返回當前元素下標與另一個元素的下標,作為結果輸出。程式碼如下:
class Solution(object):
def twoSum(self, nums, target):
for i in range(len(nums)):
if (target - nums[i]) in nums:
return [i,nums.index(target - nums[i])]
然而,實際程式設計過程中出現了這麼一個問題,Python提供的list.index(value,from,to) “左閉右開區間”,在不指定from,to的時候,該方法預設返回陣列中第一次出現該value的index值
class Solution(object):
def twoSum(self, nums, target):
for i in range(len(nums)):
if (target - nums[i]) in nums:
idx = nums.index(target - nums[i])
if i == idx:
pass
else:
return [i,idx]
然而,還是出了問題,比如說在case([0,3,4,0],0)中,應該輸出[0,3],但上面方法卻輸出了null,我的一個新思路是,是不是應該在查詢 target - nums[i] 元素的index時,設定一個from值,應該從當前元素的後面一個開始查詢元素,於是程式碼改為如下:
class Solution(object):
def twoSum(self, nums, target):
for i in range(len(nums)):
if (target - nums[i]) in nums:
idx = nums.index(target - nums[i],i+1) # 這裡設定了from
return [i,idx]
如此一來,貌似解決了case([0,3,4,0],0)的問題,結果執行的時候,case([3,4,2],6)發生執行錯誤,程式在執行第一個元素的時候,查詢到nums裡有(6-3),但是在搜index的時候,由於設定了搜尋範圍,查詢不到元素3的索引,可謂是顧此失彼。
沒辦法,只能繼續思考,如何解決這個兩難的問題,突然一個想法產生,我何不對nums陣列進行切片呢?即我在判斷陣列中是否包含 target - nums[i] 元素時,不應該對整個陣列進行查詢,而是應該對num[i+1:]進行查詢,程式碼如下:
class Solution(object):
def twoSum(self, nums, target):
for i in range(len(nums)):
num = target - nums[i]
if num in nums[i+1:]:
return [i, nums.index(num,i+1)]
最終程式測試結果:
執行用時804ms,戰勝64.84%的python提交記錄,這說明我的演算法還有很大的提升空間,時間複雜度為O(n^2),for迴圈的複雜度為O(n), x in list方法的複雜度為O(n),取切片的複雜度為O(k),index的方法為O(n),這裡複雜度的計算參考了官網。
這裡我偷懶了,直接在網上找了別人的優秀演算法,看完之後,驚為天人,在方法二中來進行說明。
2.方法二:
先看程式碼:
class Solution(object):
def twoSum(self, nums, target):
nums_dict = {}
for i, num in enumerate(nums):
if num in nums_dict:
return [nums_dict[num], i]
else:
nums_dict[target - num] = i
程式碼思路:這個演算法的核心思想是構造一個字典,字典用來儲存當前元素完成target需要的元素值作為key,當前元素的index作為value。然後遍歷過程中進行判斷,當前元素是不是屬於我想要的元素,是的話,直接輸出 [字典中該元素的下標,當前遍歷元素下標]
思考:這個演算法快在哪裡?
從時間複雜度的角度來看,第一層for迴圈是O(n),字典採用的是hash函式的結構,所以在 x in dict的查詢過程中,時間複雜度為O(1),而這裡沒用到index查詢,而是直接獲取value值,而字典的Get Item的複雜度也是O(1),所以整個演算法的時間複雜度為O(n),不過這裡的空間複雜度是O(n),用空間換時間。
最終程式測試結果: