接觸了代碼,那麼算法始終是繞不開的一個重點。python
算法對於開發人員,在平常之中的做用很大,可是對於測試人員來講,實際編碼中用到的彷佛不是不少。
不過,如今大廠的測試開發的面試,算法是必考的,並且這也的確是你的代碼功底的一項重要體現,學學沒壞處。面試
關於算法的基礎知識,以前本身也買過書,可是學習的斷斷續續的,練習刷題就更加稀少了。
因此,打算往後作一個【簡單算法】的記錄:算法
題目來自LeetCode傳送門,有興趣的童鞋能夠到上面刷題練習。數組
給定一個整數數組 nums
和一個目標值 target
,請你在該數組中找出和爲目標值的那 兩個 整數,並返回他們的數組下標。函數
你能夠假設每種輸入只會對應一個答案。可是,數組中同一個元素不能使用兩遍。學習
給定 nums = [2, 7, 11, 15], target = 9 由於 nums[0] + nums[1] = 2 + 7 = 9 因此返回 [0, 1]
忽然有了考試作題的感受,我以爲首先題目要先審清楚,而後本身嘗試用本身已有的知識去解決。
實在作不出來,也別泄氣,算法道路必定是曲折的,起碼對我來講是這樣,大佬除外。測試
另外,無論作不作出來,都要去學習下示例解法,學習解題思路,從中收穫更多。編碼
我本身嘗試着作,這題由於屬於簡單難度,我用for循環的知識進行了暴力破解,代碼以python3爲例:code
def twoSum(nums, target): for i in range(len(nums)): for j in range(i+1, len(nums)): if nums[i] + nums[j] == target: return [i, j]
其實就是2次循環,最外層的循環,從列表第一個開始遍歷,直到最後一個元素,長度就是len(nums)
。
由於題目中說,單元素不能使用兩次,因此內層的循環,就從i 以後也就是i+1
開始,直到最後一個元素。blog
拿到了2個數,就進行相加操做,與target
進行比較,若是相等,就返回出這2個元素的下標。
運行一下:
def twoSum(nums, target): for i in range(len(nums)): for j in range(i+1, len(nums)): if nums[i] + nums[j] == target: return [i, j] if __name__ == "__main__": print(twoSum2([2, 15, 11, 7], 9)) -------------結果---------------------- D:\Programs\Python\Python36\python.exe D:/練習/leecode/two_sum.py [0, 3] Process finished with exit code 0
這題雖然我作出來,可是這個解法並很差,若是遇到一個元素不少的列表,而且最後的2個值 之和 等於目標值,那麼這種狀況下,
數組裏的任意2個元素都要匹配比較一次。
時間複雜度就爲:O(N^2)。
空間複雜度還好,由於沒去去開闢額外的空間去計算,因此是:O(1)。
關於複雜度的分析,後面單獨寫一篇介紹。
上面的解法缺點就是在最壞的時候,數組裏的任意2個元素都要匹配比較一次,那麼就要來解決這個問題。
換個思路來想,遍歷列表的中的元素x,若是列表中存在 target-x
,那麼這2個數的下標就是最終咱們要的結果。
官方的建議解法用了哈希表,對於key-value這樣的存儲形式,x
跟它的下標是對應的,這樣一來,找到target-x
的時間複雜度就變成了O(1)。
因此新的解法就是:
def twoSum2(nums, target): hashtable = dict() for i, num in enumerate(nums): if target - num in hashtable: return [hashtable[target - num], i] hashtable[nums[i]] = i return []
這裏使用python,能夠建立一個空字典。再利用python中的enumerate()
函數,遍歷出列表裏的元素和下標。
在每一次的遍歷中,就能夠用目標值 target
—— 當前元素 num
,判斷這個值 在不在字典裏。
這裏用到的是Python 字典 in 操做符,用於判斷鍵是否存在於字典中。
若是在的話,那就返回 字典裏的 元素以及,下標。
由於剛開始循環的的時候,字典裏沒數據,因此當每次循環後,咱們要把此次循環的元素跟它的下標 分別 做爲 key和value放到字典裏去。
能夠加個打印看下 字典的操做過程:
def twoSum2(nums, target): hashtable = dict() for i, num in enumerate(nums): if target - num in hashtable: return [hashtable[target - num], i] hashtable[nums[i]] = i print(hashtable) return [] if __name__ == "__main__": print(twoSum2([4, 15, 3, 7, 2], 9)) =============================結果============================== D:\Programs\Python\Python36\python.exe D:/練習/leecode/two_sum.py {4: 0} {4: 0, 15: 1} {4: 0, 15: 1, 3: 2} {4: 0, 15: 1, 3: 2, 7: 3} [3, 4] Process finished with exit code 0
最終,分析解法2的複雜度:
時間複雜度—— O(N),N 是列表中的元素數量。對於每個元素 x,咱們能夠 O(1) 地尋找 target - x。
空間複雜度—— O(N),其中 N 是數組中的元素數量。主要是哈希表的開銷,在空間上的消耗。
其實也不能說解法1就是最爛的,由於算法沒有最好的算法,只有最適合的算法。
隨着需求在空間和時間的取捨的不一樣,具體決定使用哪一種算法也是不一樣的。
在這個簡單算法裏,學習和回顧到的知識點: