1. 程式人生 > >演算法與資料結構基礎 - 雜湊表(Hash Table)

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

Hash Table基礎

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

 

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

 

相關LeetCode題:

706. Design HashMap  題解 

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

771. Jewels and Stones  題解

202. Happy Number  題解

166. Fraction to Recurring Decimal  題解

720. Longest Word in Dictionary  題解

970. Powerful Integers  題解

204. Count Primes  題解

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

217. Contains Duplicate  題解

811. Subdomain Visit Count  題解

1002. Find Common Characters  題解

266. Palindrome Permutation  題解

242. Valid Anagram  題解

748. Shortest Completing Word  題解

1072. Flip Columns For Maximum Number of Equal Rows  題解

451. Sort Characters By Frequency  題解

347. Top K Frequent Elements  題解

454. 4Sum II  題解

781. Rabbits in Forest  題解

30. Substring with Concatenation of All Words  題解

 

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

 

Key-Val

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

 

相關LeetCode題:

1. Two Sum  題解

219. Contains Duplicate II  題解

953. Verifying an Alien Dictionary  題解

359. Logger Rate Limiter  題解

1086. High Five  題解

690. Employee Importance  題解

981. Time Based Key-Value Store  題解

325. Maximum Size Subarray Sum Equals k  題解

244. Shortest Word Distance II  題解

355. Design Twitter  題解 

336. Palindrome Pairs  題解

 

對映

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

 

相關LeetCode題:

246. Strobogrammatic Number  題解

205. Isomorphic Strings  題解

49. Group Anagrams  題解

249. Group Shifted Strings  題解

290. Word Pattern  題解

138. Copy List with Random Pointer  題解

535. Encode and Decode TinyURL  題解

710. Random Pick with Blacklist  題解

 

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

356. Line Reflection  題解

 

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

381. Insert Delete GetRandom O(1) - Duplicates allowed  題解

895. Maximum Frequency Stack  題解

146. LRU Cache  題解