標籤:pair nbsp pre 解答 two sum 查看 turn 字典 範圍
今天開始在LeetCode刷題,第一題為“兩數之和(Two Sum)”,整體來講這一題難度是比較低的,但還是在這個過程中遇到一些問題,以下主要記錄出現的一些問題。
這個題目比較容易想到的方法便是窮舉了,很暴力但也很直接,需要注意的一點便是向量庫Vector,自己也是前一陣子開始學資料結構才知道有這個庫(有的也稱為容器),定義計算數組長度用的方法是size()而不是length(),官方解答給的是length(),不知道是不是沒有注意到還是因為他用的代碼是Java(本人不瞭解Java),其餘不再多說。
窮舉也是我能想到唯一的方法了-_-||。。。因此看了官方題解,才知道還有雜湊表這個好東西,其基本原理我就摘用網上的原話了:使用一個下標範圍比較大的數組來儲存元素。可以設計一個函數(雜湊函數,也叫做散列函數),使得每個元素的關鍵字都與一個函數值(即數組下標,hash值)相對應,於是用這個數組單元來儲存這個元素;也可以簡單的理解為,按照關鍵字為每一個元素“分類”,然後將這個元素儲存在相應“類”所對應的地方,稱為桶。但是,不能夠保證每個元素的關鍵字與函數值是一一對應的,因此極有可能出現對於不同的元素,卻計算出了相同的函數值,這樣就產生了“衝突”,換句話說,就是把不同的元素分在了相同的“類”之中。 總的來說,“直接定址”與“解決衝突”是雜湊表的兩大特點。 (--------------------- 原理這段話來自 劍西樓 的CSDN 部落格 ,全文地址請點擊:52416583?utm_source=copy)
雜湊表是一個在時間和空間上做出權衡的經典例子。如果沒有記憶體限制,那麼可以直接將鍵作為數組的索引。那麼所有的尋找時間複雜度為O(1);如果沒有時間限制,那麼我們可以使用無序數組並進行順序尋找,這樣只需要很少的記憶體。雜湊表使用了適度的時間和空間來在這兩個極端之間找到了平衡。只需要調整雜湊函數演算法即可在時間和空間上做出取捨。( --------------------- 例子這段話來自 sam5828 的CSDN 部落格 ,全文地址請點擊:52885030?utm_source=copy)。
在網上查看了一些資料以後覺得雜湊表與字典類似,都是利用索引值對來儲存資料,那麼瞭解原理後學習hash_map的各種方法,上手!首先按照“兩遍雜湊表”的思路碼代碼,根據編譯結果提示對代碼進行不斷地改寫,最終還是沒有成功,費了好大功夫最終在Visual Studio協助文檔中看到hash_map已經是個過去式了(心中一萬頭可愛的羊駝奔過...),現在用unordered_map替代,於是最終我選用了map類,當時並沒有搞清楚兩個具體有什麼區別,只是大致瞭解了一下他們兩個的方法幾乎都是一樣的,需要注意at方法和find方法的區別,前者返回鍵對應的值,後者返回引用映射當中具有與指定鍵等效的鍵的元素的位置的迭代器。完成兩遍雜湊表以後一遍雜湊表也就順其自然完成了。
三種方法的比較:
| |
窮舉法 |
兩遍雜湊表 |
一遍雜湊表 |
| 時間複雜度 |
O(n2) |
O(n)[雜湊表尋找元素時間為O(1),建表時間為O(n) |
O(n) |
| 空間複雜度 |
O(1) |
O(n)[雜湊表建立的額外空間取決於元素數量] |
O(n) |
C++代碼貼下方:
1 //窮舉法 2 class Solution { 3 public: 4 vector<int> twoSum(vector<int>& nums, int target) { 5 for (int i = 0; i < nums.size(); i++) 6 { 7 for (int j = i + 1; j < nums.size(); j++) 8 { 9 if (nums[j] == target - nums[i]) 10 {11 return {i, j};12 }13 }14 }15 }16 };17 18 //兩遍雜湊表19 class Solution {20 public:21 vector<int> twoSum(vector<int>& nums, int target) {22 map<int, int> tmap; 23 for(int i = 0; i < nums.size(); i++) 24 tmap.insert(make_pair(nums[i], i));25 for(int i = 0; i < nums.size(); i++)26 {27 int j = target - nums[i];28 if(tmap.count(j) == 1 && tmap.at(j) != i)29 return {i, tmap.at(j)};30 }31 printf("There is no two sum solution.");32 }33 };34 35 //一遍雜湊表36 class Solution {37 public:38 vector<int> twoSum(vector<int>& nums, int target) {39 unordered_map<int, int> tmap; 40 for(int i = 0; i < nums.size(); i++) 41 {42 tmap.insert(make_pair(nums[i], i));43 int j = target - nums[i];44 if(tmap.count(j) == 1 && tmap.at(j) != i)45 return {tmap.at(j), i}; //注意此處找到符合條件元素時,tmap.at(j)的位置必然在i前方,因此輸出時順序顛倒46 47 }48 printf("There is no two sum solution.");49 }50 };
LeetCode刷題(一):Two Sum