前言
欢迎大家积极在评论区留言发表自己的看法,知无不言,言无不尽,养成每天刷题的习惯,也可以自己发布优质的解题报告,供社区一同鉴赏,吸引一波自己的核心粉丝。
今天是七月集训第七天:哈希表🔥🔥🔥
一、练习题目
二、算法思路
- 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、前缀和哈希表