LeetCode题库Hot100中哈希表题目C++

1. C++中map与unordered_map

1.1 map

map是C++中的关联式容器,按照特定的顺序用过一个pair<key,value>组合而成map容器的特点如下:

  1. map中的元素总是按照键值key进行比较排序的
  2. map支持下标访问符,即在[]中放入key,就可以找到与key对应的value。
  3. map通常被实现为平衡二叉搜索树(红黑树)。

接口函数
请添加图片描述

1.2 unorderd_map

unordered_map是一个关联容器,内部采用的是hash表结构,拥有快速检索的功能。特性如下:

  1. 关联性:通过key去检索value,而不是通过绝对地址(和顺序容器不同)
  2. 无序性:使用hash表存储,内部无序
  3. Map : 每个值对应一个键值
  4. 键唯一性:不存在两个元素的键一样
  5. 动态内存管理:使用内存管理模型来动态管理所需要的内存空间

详情请看:https://blog.csdn.net/xiaoyu_wu/article/details/121490312

2. Hot100中hashmap题目

题单

无重复字符的最长子串
两数之和
二叉树中序遍历
最小覆盖子串
和为k的数组
每日温度
只出现一次的数字
前k个高频元素
最大矩形
找到字符串中所有字母异位词
字母异位词分组

2.1 每日温度

请添加图片描述

解法一:暴力双循环(超时)

class Solution {
public:
    vector<int> dailyTemperatures(vector<int>& temperatures) {
        int n = temperatures.size();
        vector<int> res(n);
        res[n-1] = 0;

        for(int i=0; i<n; ++i){
            for(int j=i+1; j<n; ++j){
                if(temperatures[i] < temperatures[j]){
                    int ans = j - i;
                    res[i] = ans;
                    break;
                }else if((temperatures[i] >= temperatures[j]) && j == n){
                   res[i] = 0; 
                }
                
            }
        }
        return res;

    }
};

解法二:hash_map
可以看出暴力解法存在着不少重复运算,每一次都需要把i+1后面的数组重新遍历一遍。我🚪考虑到一种最极端的情况下:
[1,1,1,1,1,1,1,1,1,2] 这个数组的ans应该为[9,8,7,6,5,4,3,2,1,0]。那么我们不妨利用hashmap来存储天气与对应的下标值,注意温度为key,下标为value。
此时在有重复天气的时候不用每次遍历,只需要向哈希表中取值并且更新hashmap就可以了



class Solution {
public:
    vector<int> dailyTemperatures(vector<int>& temperatures) {
        int len = temperatures.size();
        vector<int> ans(len);  // 存储结果的数组

        unordered_map<int, int> tbl;  // 使用哈希表记录温度值和对应的索引

        for (int i = 0; i < len; i++) {
            auto t = tbl.find(temperatures[i]);  // 查找当前温度在哈希表中的记录

            // 如果找到了记录
            if (t != tbl.end()) {
                // 如果记录中的索引大于当前索引,说明已经找到下一个温度更高的日子
                if (t->second > i) {
                    ans[i] = t->second - i;
                    continue;
                }
                
                // 如果记录中的索引为 -1,说明已经遍历过数组但未找到更高温度的日子
                if (t->second == -1) {
                    continue;
                }
            }

            // 遍历当前温度之后的数组
            for (int j = i + 1; j < len; j++) {
                // 如果找到了下一个温度更高的日子
                if (temperatures[j] > temperatures[i]) {
                    ans[i] = j - i;  // 记录两天之间的间隔
                    tbl[temperatures[i]] = j;  // 更新哈希表中的记录
                    break;
                }
            }

            // 如果 ans[i] 仍然为 0,说明在之后的日子中未找到更高温度
            if (ans[i] == 0) {
                tbl[temperatures[i]] = -1;  // 记录为 -1,表示已经遍历过但未找到
            }
        }

        return ans;
    }
};

解法三:单调栈

class Solution {
public:
    vector<int> dailyTemperatures(vector<int>& temperatures) {
        int n = temperatures.size();
        vector<int> res(n);
        // 栈内存放的是天气的下标数量
        stack<int> stk;

        for(int i=0; i<n; ++i){
            while(!stk.empty() && temperatures[i] > temperatures[stk.top()]){
                //当第一个天气大与栈顶元素出现时候,当前栈顶元素对应的res值为
                //出现大于它天气元素的下标数 - 他自身的下标数
                res[stk.top()] = i - stk.top();
                stk.pop();
            }
            // 入栈
            stk.push(i);
        } 
    return res;
    }
};

2.2 只出现一次的数字

方法一:哈希辅助表
思路:若第一次出现,插入哈希集,第二次出现,冲哈希集内删除,最后剩下的就是那个只出现一次的数字。

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        unordered_set<int> ust;
        int ans;

        for(auto x : nums){
            if(ust.count(x)){
                ust.erase(x);
            }else{
                ust.insert(x);
            }
        }
        for(auto m : ust){
            ans = m;
        }
        return ans;
    }
};

解法二:异或运算
异或运算特点:相同两个数异或之后为0。任何数字与0异或之后等于本身。异或运算满足交换律结合律。
那么此题中的数字可以抽象为:[a,a,b,b,c,c,…,x],也就是说数组中这些数字一起异或结果为x,也就是多余数字本身。

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int x = 0;
        for (int num : nums)  // 1. 遍历 nums 执行异或运算
            x ^= num;
        return x;            // 2. 返回出现一次的数字 x
    }
};

2.3 前K个高频元素

请添加图片描述

解法一:哈希表+优先队列

class Solution {
public:
    vector<int> topKFrequent(vector<int>& nums, int k) {
    //1.map记录元素出现的次数
        unordered_map<int,int>map;//两个int分别是元素和出现的次数
        for(auto& c:nums){
            map[c]++;
        }
    //2.利用优先队列,将出现次数排序
        //自定义优先队列的比较方式,小顶堆
        struct myComparison{
            bool operator()(pair<int,int>&p1,pair<int,int>&p2){
                return p1.second>p2.second;//小顶堆是大于号
            }
        };
        //创建优先队列
        priority_queue<pair<int,int>,vector<pair<int,int>>,myComparison> q;
        //遍历map中的元素
        //1.管他是啥,先入队列,队列会自己排序将他放在合适的位置
        //2.若队列元素个数超过k,则将栈顶元素出栈(栈顶元素一定是最小的那个)
        for(auto& a:map){
            q.push(a);
            if(q.size()>k){
               q.pop(); 
            }
        }
        //将结果导出
        vector<int>res;
        while(!q.empty()){
            res.emplace_back(q.top().first);
            q.pop();
        }
        return res;

    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值