算法與數據結構基礎 - 哈希表(Hash Table)


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

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM