Hash Table基礎
雜湊表(Hash Table)是常用的資料結構,其運用雜湊函式(hash function)實現對映,內部使用開放定址、拉鍊法等方式解決雜湊衝突,使得讀寫時間複雜度平均為O(1)。
HashMap(std::unordered_map)、HashSet(std::unordered_set)的原理與Hash Table一樣,它們的用途廣泛、用法靈活,接下來側重於介紹它們的應用。
相關LeetCode題:
集合
如果僅需要判斷元素是否存在於某個集合,我們可以使用結構HashSet(std::unordered_set)。例如 LeetCode題目 349. Intersection of Two Arrays:
// 349. Intersection of Two Arrays vector<int> intersection(vector<int>& nums1, vector<int>& nums2) { unordered_set<int> s1(nums1.begin(),nums1.end()); unordered_set<int> s2(nums2.begin(),nums2.end()); vector<int> res; for(auto& a:s1) if(s2.count(a)) res.push_back(a); return res; }
相關LeetCode題:
349. Intersection of Two Arrays 題解
720. Longest Word in Dictionary 題解
計數
如果需要對元素進行計數,我們可以使用結構HashMap(std::unordered_map),元素如取值範圍固定可以用Array(std::vector),例如LeetCode題目 217. Contains Duplicate:
// 217. Contains Duplicate bool containsDuplicate(vector<int>& nums) { unordered_map<int,int> m; for(int x:nums) if(m[x]++==1) return true; return false; }
相關LeetCode題:
266. Palindrome Permutation 題解
748. Shortest Completing Word 題解
451. Sort Characters By Frequency 題解
30. Substring with Concatenation of All Words 題解
在滑動視窗演算法中常使用HashMap計數,關於滑動視窗演算法,詳見:演算法與資料結構基礎 - 滑動視窗(Sliding Window)
Key-Val
進一步地,HashMap表示一種Key-Val (或ID-屬性) 關係,這裡Val可以是計數、下標(index)等等。
相關LeetCode題:
953. Verifying an Alien Dictionary 題解
981. Time Based Key-Value Store 題解
244. Shortest Word Distance II 題解
對映
更一般地,HashMap表示一種對映關係,意義在於O(1)時間複雜度完成由 A->B 的對映。
相關LeetCode題:
535. Encode and Decode TinyURL 題解
HashMap與Prefix sum
利用HashMap和Prefix sum,我們可以在O(n)時間複雜度求解一類子序列求和問題,其中HashMap用於計數,例如LeetCode題目 560. Subarray Sum Equals K:
// 560. Subarray Sum Equals K int subarraySum(vector<int>& nums, int k) { unordered_map<int,int> m; m[0]=1; int sum=0,res=0; for(auto& a:nums){ sum+=a; res+=m[sum-k]; m[sum]++; } return res; }
相關LeetCode題:
930. Binary Subarrays With Sum 題解
325. Maximum Size Subarray Sum Equals k 題解
HashMap與圖形問題
HashMap可以應用於二維圖形的一些問題求解,以尤拉距離、斜率、x/y座標等為key,以計數、x/y座標為val。圖形問題中HashMap的對映關係不是那麼直觀和明顯,需要單獨計算key、仔細甄別對映關係。
相關LeetCode題:
939. Minimum Area Rectangle 題解
HashMap與vector/list/stack結合
HashMap與vector、list、stack等資料結構可以結合成為複合資料結構,這樣可以既用到HashMap O(1)的優點,也用到vector支援下標操作、list增刪節點快、stack先進後出的特點。例如 LeetCode題目 380. Insert Delete GetRandom O(1):
// 380. Insert Delete GetRandom O(1) vector<int> v; unordered_map<int,int> m;
以上用vector儲存元素,unordered_map儲存元素和對應下標;getRandom函式利用vector下標操作,而刪除元素時,使用unordered_map取得被刪元素、將vector末尾元素與其對調,利用了HashMap O(1)的優點。
相關LeetCode題:
380. Insert Delete GetRandom O(1) 題解
895. Maximum Frequency Stack 題解