【笔记】哈希表

本系列总计六篇文章,是 基于STL实现的笔试题常考七大基本数据结构 该文章在《代码随想录》和《labuladong的算法笔记》题目中的具体实践,每篇的布局是这样的:开头是该数据结构的总结,然后是在不同场景的应用,以及不同的算法技巧。本文是系列第三篇,介绍了哈希表的相关题目,重点是要掌握STL的set和map,注意N数之和问题,用双指针最方便。

下面文章是在《代码随想录》和《labuladong的算法笔记》题目中的具体实践:
【笔记】数组
【笔记】链表
【笔记】哈希表
【笔记】字符串
【笔记】栈与队列
【笔记】二叉树

0、总结

  • 哈希表用来快速判断一个元素是否出现在集合里

  • 一般常用数组、unordered_setunordered_map 这三种数据结构实现哈希表,后两者的底层实现是哈希表,无序、数值(key)不可重复、数值(key)不可修改、查询和增删效率都是 O(1)

  • set,multiset,map,multimap底层是红黑树,当要求key有序、重复时,可以选用

  • 两数、三数、四数之和问题,用 双指针法 最方便

1、set 作为哈希表

349. 两个数组的交集 - 力扣(LeetCode)

思路:输出交集,要求去重、不考虑输出结果的顺序,因此选用unordered_set

注意:set和vector互相转化可以用构造函数直接实现,不需要遍历;set增加元素用insert;用auto更方便

class Solution {
   
public:
    vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {
   
        vector<int> result;
        // 要去重,所以用unordered_set
        unordered_set<int> result_set, nums1_set;
        // unordered_set<int> nums_set(nums1.begin(), nums1.end());
        for (int i : nums1)
            nums1_set.insert(i);
        for (int i : nums2) {
   
            if (nums1_set.find(i) != nums1_set.end()) {
   
                result_set.insert(i);
            }
        }
        // return vector<int>(result_set.begin(), result_set.end());
        for (auto it = result_set.begin(); it != result_set.end(); it++)
            result.push_back(*it);
        return result;
    }
};

202. 快乐数 - 力扣(LeetCode)

思路:用set判断集合中的某个元素是否出现过,若出现过,代表有循环,此数并非快乐数,应及时return

注意:按位取数的写法应牢记,n不为0的情况下,不断地先%10,再/10,这样可以低位到高位取数

class Solution {
   
public:
    bool isHappy(int n) {
   
        unordered_set<int> set;
        while(1) {
   
            int sum = getSum(n);
            if (sum == 1) return true;
            if (set.find(sum) != set.end()) {
   
                return false;
            } else {
   
                set.insert(sum);
            }
            n = sum;
        }
    }
    int getSum(int n) {
   
        int sum = 0;
        while (n) {
   
            sum += pow(n % 10, 2);
            n /= 10;
        }
        return sum;
    }
};

2、map 作为哈希表

350. 两个数组的交集 II - 力扣(LeetCode)

思路:与349的区别是,不去重,若公共元素是a,返回结果中a出现的次数,应与a在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值),要用unordered_map

进阶:

  • 如果给定的数组已经排好序呢?你将如何优化你的算法?用双指针只需 O(n) 的时间复杂度

  • 如果 nums1 的大小比 nums2 小,哪种方法更优?较小的数组用hash存储,然后在另一个数组中寻找

  • 如果 nums2 的元素存储在磁盘上,内存是有限的,并且你不能一次加载所有的元素到内存中,你该怎么办?

    还是较小的数组用hash存储,然后在另一个数组中,每次读取出一部分数据进行寻找

class Solution {
   
public:
    vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {
   
        vector<int> result;
        // 题目不要求去重
        unordered_map<int, int> map;
        for (int i : nums1)
            map[i]++;
        for (int i : nums2) {
   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值