九日算法C++
没有之前的,懒
不知道为什么链接关不掉
- 九日算法C++
- 前言
- 一、内容介绍
- 二、练习题目(来自力扣)
- 三、代码思路
- 1.[面试题 17.05. 字母与数字](https://leetcode.cn/problems/find-longest-subarray-lcci/submissions/)
- 2.[970. 强整数](https://leetcode.cn/problems/find-longest-subarray-lcci/submissions/)
- 3.[914. 卡牌分组](https://leetcode.cn/problems/x-of-a-kind-in-a-deck-of-cards/)
- 4.[1497. 检查数组对是否可以被 k 整除](https://leetcode.cn/problems/check-if-array-pairs-are-divisible-by-k/)
- 晚安玛卡巴卡
前言
2022の夏天,半壶水响叮当的我决定充实一下自我
一、内容介绍
学校老师:key——value,一一对应
unordered_map<char,int> hash;
hash.insert(pair<char,int>('A', 10));
插入(insert)问题:哈希冲突,不能一一对应,则扩容,换划分规则
查找(find):找key,找不到返回.end(),冲突查找:给他来个桶,线性或指数增长查找
使用:不用你考虑冲突,一一对应双射函数就行,可理解为2*n无index矩阵,例:电话簿
二、练习题目(来自力扣)
项目 | 完成情况 |
---|---|
面试题 17.05. 字母与数字 | 已 |
970. 强整数 | 已 |
914. 卡牌分组 | 已 |
1497. 检查数组对是否可以被 k 整除 | 已 |
三、代码思路
1.面试题 17.05. 字母与数字
思想:转哈希表为一对一势能(最小等势能)
(1)与原数组index一一对应,做势能数组(??)
(2)找等势能点 左l =势能+1 到 右r =i,中长度最长len
class Solution {
public:
vector<string> findLongestSubarray(vector<string>& array) {
int sum[100010];
int i;
int pre =0;
for(i =0;i <array.size(); ++i){
sum[i] =pre;//上一个
if(array[i][0] >='0' && array[i][0] <='9'){//是数 +1
sum[i] +=1;
}else {
sum[i] -=1;
}
pre =sum[i];// 记录长
}
//窗口l,r
unordered_map<int, int> hash;
hash[0] = -1; //hash[最小等势能] ==位置,记录未开始为0势能
int l =0,r =-1,maxlen =0;
for(i =0;i <array.size(); ++i){
if(hash.find(sum[i]) !=hash.end()) {//找到
int len =i -hash[sum[i]];//窗口长
if(len >maxlen){
maxlen =len;
l =hash[sum[i]] +1;
r =i;//
}
}
else hash[ sum[i] ] =i;// 无, 则覆盖
}
vector<string> ret;
for(i =l;i <=r; ++i){
ret.push_back( array[i] );
}
return ret;
}
};
2.970. 强整数
思想:一维数组条件遍历
(1)先缓存x,y的幂积,到xs,ys,注意底数为1
(2)遍历
class Solution {
public:
vector<int> powerfulIntegers(int x, int y, int bound) {
vector<int> xs, ys;
int i,j;
int prex =1, prey =1;
for(i =1; prex <= bound; ++i){
xs.push_back(prex);
prex *=x;
if(x ==1) {
break;
}
}
for(i =1; prey <= bound; ++i){
ys.push_back(prey);
prey *=y;
if(y ==1) {
break;
}
}
unordered_set<int> ret;
for(i =0;i <xs.size(); ++i){
for(j =0;j <ys.size(); ++j){
int val =xs[i] + ys[j];
if(val <= bound){
ret.insert(val);
}
}
}
return vector<int>(ret.begin(), ret.end());
}
};
3.914. 卡牌分组
思想:等价划分
(1)gcd,最小公约数,辗转相除法,迭代函数,牛逼
(2)hash:key:deck某数——value:某数出现次数
(3)一组卡:1X4,2X2,故找到出现次数最小公约数totgcd
class Solution {
int gcd(int a, int b){//最大公约数,辗转相除k
return !b? a: gcd(b , a%b);//b=0 return a
}
public:
bool hasGroupsSizeX(vector<int>& deck) {
int hash[10010];
int n =deck.size();
int max_num =-1;
memset(hash , 0 ,sizeof(hash));//初始化哈希表为0
for(int i =0; i <n; ++i){
++hash[ deck[i] ];//对于deck[i]分割,映射为出现次数
max_num = max(max_num , deck[i]);//hash范围
}
int totgcd =-1;
for(int i =0; i <=max_num; ++i){
if(hash[i]){//有出现次数
if(totgcd == -1){
totgcd = hash[i];
}else {
totgcd = gcd(totgcd , hash[i]);
}
if(totgcd ==1) return false;
}
}
return true;//最大公约数不为1
}
};
4.1497. 检查数组对是否可以被 k 整除
思想:等价划分(分块)
(1)转哈希表:key:余数——value:等价类个数
(2)i 与 k-i余数的个数相同,且0整除树为偶数
class Solution {
public:
bool canArrange(vector<int>& arr, int k) {
int n =arr.size();
int hash[k +1];
memset(hash , 0 , sizeof(hash));
for(int i =0; i <n; ++i){
int mod =(arr[i]%k +k) %k;//防止负数
++hash[ mod ];
}
if(hash[0] & 1) return false;//取第一位,等价除余2
for(int i =1;i <k; ++i){
if(hash[i] != hash[k-i]){
return false;
}
if(i > (k/2 +1)){
return true;
}
}
return true;
}
};
晚安玛卡巴卡
跟刷题大佬(B站英雄在哪里),早上五点等你