《七月集训》(第七天)——哈希表

前言

        欢迎大家积极在评论区留言发表自己的看法,知无不言,言无不尽,养成每天刷题的习惯,也可以自己发布优质的解题报告,供社区一同鉴赏,吸引一波自己的核心粉丝。
        今天是七月集训第七天:哈希表🔥🔥🔥
在这里插入图片描述

一、练习题目

        970. 强整数
        914. 卡牌分组
        1497. 检查数组对是否可以被 k 整除
        面试题 17.05. 字母与数字

二、算法思路

  • 1、970. 强整数:🔥数据量100那就直接暴力搜索枚举所有情况,记得注意x和y是1的情况要break不然是一直死循环的。
  • 2、914. 卡牌分组:🔥🔥🔥这道题需要一定数论的基础的,比如给的示例1:[1,2,3,4,4,3,2,1],1,2,3,4均出现了两次最大公因数为2可以分组,再例如[1,2,3,4,4,3,2,1,1,1,5,5],1出现了四次,2,3,4,5出现了两次,最大公因数为2可以分组,而[1,1,1,2,2,2,3,3] ,1,2出现了三次,3出现了两次,最大公因数为1不能分组。
  • 3、1497. 检查数组对是否可以被 k 整除:🔥🔥🔥这道题也需要数论的知识。
  • 4、面试题 17.05. 字母与数字:🔥🔥🔥前缀和加哈希表。

三、源码剖析

// 970. 强整数
class Solution {
public:
    vector<int> powerfulIntegers(int x, int y, int bound) {
        unordered_set<int> t;
        for(int i = 0; ;++i) {
            int curx = pow(x, i);
            if(curx >= bound) { //(1)
                break;
            }
            for(int j = 0; ;++j) {
                int cury = pow(y, j);
                if(curx + cury > bound) { //(2)
                    break;
                }
                t.insert(curx + cury);
                if(y == 1) {
                    break;
                }
            }
            if(x == 1) {
                break; //(3)
            }
        }
        return vector<int> (t.begin(), t.end());
    }
};
  • 1、先计算x的i次方,判断是不是超过边界,超过了就break;
  • 2、再写一层循环去算y的j次方,判断和之前的x的i次方相加是不是超过边界;
  • 3、记得x和y为1的情况要break。
// 914. 卡牌分组
class Solution {
public:
    int gcd(int a, int b) {
        return b == 0 ? a : gcd(b, a%b);
    } //(1)
    bool hasGroupsSizeX(vector<int>& deck) {
        int hash[10010];
        memset(hash, 0, sizeof(hash));
        for(auto i : deck) {
            hash[i]++;
        }
        int totgcd = -1;
        for(int i = 0; i < deck.size(); ++i) {
            if(hash[i]) {
                if(totgcd == -1) {
                    totgcd = hash[i];
                } else {
                    totgcd = gcd(totgcd, hash[i]);
                }
            }
        }
        return totgcd > 1; //(2)
    }
};
  • 1、求最小公约数;
  • 2、用哈希表统计卡牌出现的次数,求最大公约数是不是 > 1,为1的话是不能分组的。
// 1497. 检查数组对是否可以被 k 整除
class Solution {
public:
    bool canArrange(vector<int>& arr, int k) {
        int hash[100010];
        memset(hash, 0, sizeof(hash));
        for(int i = 0; i < arr.size();  ++i) {
            int mod = (arr[i] % k + k) % k; //(1)
            hash[mod]++;
        }

        if(hash[0] & 1) {
            return false; //(2)
        }
        for(int i = 1; i < k; ++i) {
            if(hash[i] != hash[k - i]) {
                return false;
            }
        }
        return true;
    }
};
  • 1、对每一个数和k取模,如果是负数取模后还是负数,所以需要加上k,然后在哈希表中查找余数相加为k的元素个数是否相等,不相等就返回false最后返回true;
  • 2、特殊的如果余数为0的话他们内部需要两两组合,这时候需要特殊判断这个等价类的个数是否是偶数。
// 面试题 17.05.  字母与数字
class Solution{
    public:
    vector<string> findLongestSubarray(vector<string>& array) {
        int prev[100010];
        unordered_map<int,int> map;
        prev[0]=0;
        for(int i=0;i<array.size();++i){
            prev[i+1]=array[i][0]>='0'&&array[i][0]<='9'?prev[i]+1:prev[i]-1;
        }
        map[0]=-1;
        int l=0,r=-1,max=-0x3f3f3f3f;
        for(int i=0;i<array.size();++i){
            if(map.find(prev[i+1])!=map.end()){
                int len=i-map[prev[i+1]];
                if(len>max){
                    max=len;
                    l=map[prev[i+1]]+1;
                    r=i;
                }
            }else {
                    map[prev[i+1]]=i;
            }
        }
        vector<string> ans;
        for(int i=l;i<=r;++i){
            ans.push_back(array[i]);
        }
        return ans;
    }
};


  • 1、前缀和哈希表
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值