目录
- LeetCode #349:Intersection of Two Arrays 两个数组的交集
- LeetCode #383:Ransom Note 赎金信
- LeetCode #454:4Sum II - 四数相加 II
本系列文章仅是 GitHub 大神 @halfrost 的刷题笔记 《LeetCode Cookbook》的提纲以及示例、题集的 C++转化。原书请自行下载学习。
本篇文章涉及新手应该优先刷的几道经典哈希表算法题,分两篇文章,以后会更新“二刷”“三刷”等等。
LeetCode #349:Intersection of Two Arrays 两个数组的交集

 给定两个数组,计算它们的交集。
实际上,就是查找 nums2 的元素是否在 nums1 中,只要是从一堆数中查找一个数,那么均可以考虑哈希查找,而对于未知数目与数值的情况,我们使用 unordered set 来解决。
class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        unordered_set<int> num_set(nums1.begin(), nums1.end());   //使用 nums1 初始化哈希集合
        vector<int> res;
        //遍历 nums2,检查元素是否在哈希集合中
        for (int num : nums2) {
            if (num_set.count(num)) {   //如果元素在哈希集合中,则添加到结果列表中
                res.push_back(num);
                num_set.erase(num);     //确保交集元素不会重复
            }
        }
        return res;
    }
};
由于使用了内置的库函数,该算法效率并不高。我们可以直接使用哈希表构建所谓的“集合”,提高代码执行效率:
class Solution {
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
        vector<int>result;
        unordered_map<int ,int>hash;
        for(const auto &num : nums1) hash[num] = 1;
        for(const auto &num : nums2) {
            --hash[num];
            if(hash[num] == 0) result.push_back(num);
        }
        return result;
    }
};
LeetCode #383:Ransom Note 赎金信

 给定一个赎金信( ransomNote )字符串和一个杂志( magazine )字符串。
判断 ransomNote 能不能由 magazine 里的字符串构成。可以返回 true ,否则返回 false 。
类似于上篇文章的 #242 有效字母异位词,找出哈希函数 f(key) = key - 'a' ,对应出每个字母在哈希表中的索引,随后以 vector 类模拟哈希表:
- 遍历 magazine字符串,哈希表中对应的字符增加。
- 遍历 ransomNote字符串,自减哈希表中对应的字符,如果在自减之后该位置的值小于 0,则说明magazine中没有足够的字符构建ransomNote,直接返回false。
- 遍历结束,返回 true。
class Solution {
public:
    bool canConstruct(string ransomNote, string magazine) {
        if (ransomNote.size() > magazine.size()) return false;  // ransomNote 长度过长,必然不满足题意
        vector<int> cnt(26);  //初始化含有 26 个元素的哈希函数
        for (auto & c : magazine) cnt[c - 'a']++;  //遍历 magazine,每个字符加入哈希表
        for (auto & c : ransomNote) {
            cnt[c - 'a']--;
            if (cnt[c - 'a'] < 0) return false;
        }
        return true;
    }
};
LeetCode #454:4Sum II - 四数相加 II

给定 4 个长度为 n 的整数数组,计算有多少个元组( i , j , k , l )能满足:
nums[i] + nums[j] + nums[k] + nums[l] == 0 。
这道题与上篇文章提及的 4Sum 问题是基本一致的,但是我们在这里尝试使用哈希查找解决。之前我们使用哈希查找解决 3Sum 问题只是为了练习哈希表的使用,然而这一问题则体现出哈希查找的优势。
思路大致如下:
- 初始化哈希表。
- 分组:nums1和nums2一组,nums3和nums4一组。
- 分别对 nums1和nums2进行遍历,将所有nums1和nums2的值之和作为哈希表的key,和的次数作为哈希表的value。
- 分别对 nums3和nums4进行遍历,若-(nums1[k] + nums4[l])在哈希表中,则将对应的值累加进答案。
class Solution {
public:
    int fourSumCount(vector<int>& A, vector<int>& B, vector<int>& C, vector<int>& D) {
        unordered_map<int, int> countAB;
        for (int u : A) for (int v : B) ++countAB[u + v];  //统计两个数组中的元素之和,同时统计出现的次数,放入 map
        int ans = 0;
        //统计剩余的两个元素的和,在 map 中找是否存在相加为 0 的情况,同时记录次数
        for (int u : C) for (int v : D) if (countAB.count(-u - v)) ans += countAB[-u - v];
        return ans;
    }
};
以空间换时间,该算法的时间复杂度、空间复杂度均为 O ( n 2 ) \ O(n^2) O(n2) 。




















