# LeetCode 1. Two Sum ## 題目 > Given an array of integers `nums` and an integer `target`, return indices of the two numbers such that they add up to `target`. > > You may assume that each input would have **exactly one solution**, and you may not use the same element twice. > > You can return the answer in any order. ## 解析 經典的 LeetCode 第一題。 題目要我們從給定的數組 `nums` 中,找出相異的兩數使之總和為 `target` ,並回傳該兩數的 index,順序不拘。 ### Brute Force 直覺的 BF 解法,迭代兩次 `nums` 以嘗試每一種可能的組合,若兩數相加符合題目要求的 `target` 就回傳 index。 ```cpp class Solution { public: vector<int> twoSum(vector<int>& nums, int target) { for(int i = 0; i < nums.size()-1; i++) for(int j = i+1; j < nums.size(); j++) if(nums[i] + nums[j] == target) return {i, j}; // 這裡不會執行 return {}; } }; ``` 這裡要特別注意到第二次的 `for` 迴圈,若從`j = i` 開始,會造成相同的數重複計算的情形,導致結果出錯,因此這裡只需要從 `j = i+1` 開始就好了。 - Time Complexity : $O(n^2)$ - 由於迭代兩次 `nums` 數組,時間複雜度為$O(n^2)$。 - Space Complexity : $O(1)$ - 沒有使用任何額外儲存結構,空間複雜度為$O(1)$。 ### Hash Map 由於此題目需要頻繁的查找,因此若使用可以增加查找效率的資料結構就會很有幫助,而這個結構就是查找複雜度為 $O(1)$ 的 **Hash Map**。 (注意在 c++ 中的 Hash Map 為 `unordered_map`,而不是一般的 `map`,`map` 底層為 RB-Tree 結構,查找需要花費 $O(\log n)$)。 我們用此結構把目前看過的數字加入其中,在之後看其他數字時,便可以用 $O(1)$ 的時間來查詢是否可以與之前已經看過的數字配對。 ```cpp class Solution { public: vector<int> twoSum(vector<int>& nums, int target) { unordered_map<int, int> map; for(int i = 0; i < nums.size(); i++){ if(map.find(target - nums[i]) != map.end()) return {i, map[target - nums[i]]}; map[nums[i]] = i; } return {}; } }; ``` 我們將 `target` 減去現在看到的數字,所得即為與之配對的數字,接著檢查我們是否已經有看過(即存在 `map` 裡),若有則回傳解答,若無則將此數字加入 `map` 裡,供下次查找用。 - Time Complexity : $O(n)$ - 由於只迭代一次 `nums` 數組,`insert`、`find` 等操作皆為 $O(1)$,因此時間複雜度為$O(n)$。 - Space Complexity : $O(n)$ - 使用了 `unordered_map` 儲存資料,最差狀況為 $O(n)$。 ## 題目連結 [1. Two Sum](https://leetcode.com/problems/two-sum/) ###### tags: `LeetCode` `Blind75`