演算法與資料結構基礎 - 雜湊表(Hash Table)

bangerlee發表於2019-08-05

Hash Table基礎

雜湊表(Hash Table)是常用的資料結構,其運用雜湊函式(hash function)實現對映,內部使用開放定址、拉鍊法等方式解決雜湊衝突,使得讀寫時間複雜度平均為O(1)。

 

HashMap(std::unordered_map)、HashSet(std::unordered_set)的原理與Hash Table一樣,它們的用途廣泛、用法靈活,接下來側重於介紹它們的應用。

 

相關LeetCode題:

705. Design HashSet  題解

 

集合

如果僅需要判斷元素是否存在於某個集合,我們可以使用結構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  題解

202. Happy Number  題解

720. Longest Word in Dictionary  題解

970. Powerful Integers  題解

36. Valid Sudoku  題解

 

計數

如果需要對元素進行計數,我們可以使用結構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題:

811. Subdomain Visit Count  題解

266. Palindrome Permutation  題解

748. Shortest Completing Word  題解

451. Sort Characters By Frequency  題解

454. 4Sum II  題解

30. Substring with Concatenation of All Words  題解

 

在滑動視窗演算法中常使用HashMap計數,關於滑動視窗演算法,詳見:演算法與資料結構基礎 - 滑動視窗(Sliding Window)

 

Key-Val

進一步地,HashMap表示一種Key-Val (或ID-屬性) 關係,這裡Val可以是計數、下標(index)等等。

 

相關LeetCode題:

219. Contains Duplicate II  題解

953. Verifying an Alien Dictionary  題解

1086. High Five  題解

981. Time Based Key-Value Store  題解

244. Shortest Word Distance II  題解

355. Design Twitter  題解 

 

對映

更一般地,HashMap表示一種對映關係,意義在於O(1)時間複雜度完成由 A->B 的對映。

 

相關LeetCode題:

205. Isomorphic Strings  題解

49. Group Anagrams  題解

249. Group Shifted Strings  題解

290. Word Pattern  題解

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題:

560. Subarray Sum Equals K  題解

525. Contiguous Array  題解

930. Binary Subarrays With Sum  題解

325. Maximum Size Subarray Sum Equals k  題解

554. Brick Wall  題解

 

HashMap與圖形問題

HashMap可以應用於二維圖形的一些問題求解,以尤拉距離、斜率、x/y座標等為key,以計數、x/y座標為val。圖形問題中HashMap的對映關係不是那麼直觀和明顯,需要單獨計算key、仔細甄別對映關係。

 

相關LeetCode題:

447. Number of Boomerangs  題解

939. Minimum Area Rectangle  題解

149. Max Points on a Line  題解

 

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  題解

146. LRU Cache  題解

 

 

相關文章