1. 程式人生 > 實用技巧 >LeetCode——1. 兩數之和

LeetCode——1. 兩數之和

題目:
給定一個整數陣列 nums 和一個目標值 target,請你在該陣列中找出和為目標值的那 兩個 整數,並返回他們的陣列下標。

你可以假設每種輸入只會對應一個答案。但是,陣列中同一個元素不能使用兩遍。

示例:

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

因為 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

官方題解:

方法一:暴力列舉

思路及演算法

最容易想到的方法是列舉陣列中的每一個數 x,尋找陣列中是否存在 target - x。

當我們使用遍歷整個陣列的方式尋找 target - x 時,需要注意到每一個位於 x 之前的元素都已經和 x 匹配過,因此不需要再進行匹配。而每一個元素不能被使用兩次,所以我們只需要在 x 後面的元素中尋找 target - x。

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        n = len(nums)
        for i in range(n):
            for j in range(i + 1, n):
                if nums[i] + nums[j] == target:
                    return [i, j]
        
        return []

複雜度分析

  • 時間複雜度:O(N^2)O
    (N2),其中 NN 是陣列中的元素數量。最壞情況下陣列中任意兩個數都要被匹配一次。
  • 空間複雜度:O(1)O(1)。

方法二:雜湊表

思路及演算法

注意到方法一的時間複雜度較高的原因是尋找 target - x 的時間複雜度過高。因此,我們需要一種更優秀的方法,能夠快速尋找陣列中是否存在目標元素。如果存在,我們需要找出它的索引。

使用雜湊表,可以將尋找 target - x 的時間複雜度降低到從 O(N)O(N) 降低到 O(1)O(1)。

這樣我們建立一個雜湊表,對於每一個 x,我們首先查詢雜湊表中是否存在 target - x,然後將 x 插入到雜湊表中,即可保證不會讓 x 和自己匹配。

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        hashtable = dict()
        for i, num in enumerate(nums):
            if target - num in hashtable:
                return [hashtable[target - num], i]
            hashtable[nums[i]] = i
        return []

複雜度分析

時間複雜度:O(N)O(N),其中 NN 是陣列中的元素數量。對於每一個元素 x,我們可以 O(1)O(1) 地尋找 target - x。

空間複雜度:O(N)O(N),其中 NN 是陣列中的元素數量。主要為雜湊表的開銷。

高贊回答:

def two_sum(nums, target):
    """這樣寫更直觀,遍歷列表同時查字典"""
    dct = {}
    for i, n in enumerate(nums):
        cp = target - n
        if cp in dct:
            return [dct[cp], i]
        else:
            dct[n] = i