【簡單算法】1.兩數之和,給定整數數組和目標值,找出數組中2數之和等於目標值的元素

接觸了代碼,那麼算法始終是繞不開的一個重點。python

算法對於開發人員,在平常之中的做用很大,可是對於測試人員來講,實際編碼中用到的彷佛不是不少。
不過,如今大廠的測試開發的面試,算法是必考的,並且這也的確是你的代碼功底的一項重要體現,學學沒壞處。面試

關於算法的基礎知識,以前本身也買過書,可是學習的斷斷續續的,練習刷題就更加稀少了。
因此,打算往後作一個【簡單算法】的記錄:算法

  • 第一,是爲了梳理解題思路,加深鞏固。
  • 第二,在學習解題的過程當中,將薄弱的代碼環節、算法基礎補全。
  • 第三,算是對算法練習的一個督促。

題目來自LeetCode傳送門,有興趣的童鞋能夠到上面刷題練習。數組

1、題目:兩數之和

描述

給定一個整數數組 nums 和一個目標值 target,請你在該數組中找出和爲目標值的那 兩個 整數,並返回他們的數組下標。函數

你能夠假設每種輸入只會對應一個答案。可是,數組中同一個元素不能使用兩遍。學習

示例

給定 nums = [2, 7, 11, 15], target = 9

由於 nums[0] + nums[1] = 2 + 7 = 9
因此返回 [0, 1]

解題

忽然有了考試作題的感受,我以爲首先題目要先審清楚,而後本身嘗試用本身已有的知識去解決。
實在作不出來,也別泄氣,算法道路必定是曲折的,起碼對我來講是這樣,大佬除外。測試

另外,無論作不作出來,都要去學習下示例解法,學習解題思路,從中收穫更多。編碼

1. 解法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. 解法2

上面的解法缺點就是在最壞的時候,數組裏的任意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就是最爛的,由於算法沒有最好的算法,只有最適合的算法。
隨着需求在空間和時間的取捨的不一樣,具體決定使用哪一種算法也是不一樣的。

2、小結

在這個簡單算法裏,學習和回顧到的知識點:

  • 哈希表的優勢
  • python的enumerate()函數的運用
  • Python 字典 in 操做符,用於判斷鍵是否存在於字典中
相關文章
相關標籤/搜索