哈希+按输入顺序访问
1041
//1.核心问题:哈希+按输入顺序访问
// 解决:维护两个表:(1)index[i]=input, hash[input]=cnt
#include <cstdio>
#include <vector>
using namespace std;
vector<int>myHash(100010, 0);
vector<int>index;
int main() {
int n, result=-1;
scanf("%d", &n);
index.resize(n);
for (int i = 0; i < n; i++) {
scanf("%d", &index[i]);
myHash[index[i]]++;
}
for (int i = 0; i < index.size(); i++) {
if (myHash[index[i]] == 1) {
result = index[i];
break;
}
}
if (result == -1)printf("None");
else printf("%d", result);
return 0;
}
哈希+映射字母
1050
//1.!!!!输入的string中有空格, 注意使用getline()
//2.思想转弯: 一开始是想尽办法如何快速在string中查找元素, 但,因为str都映射到字母上, 只要维护一个字母表,最后在遍历时决定是否输出即可
//测试时做
//1.不用怀疑ASCII里面有 空白字符
//2.getline可以得到回车
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
string input, sub;
vector<int>myHash(256);
int main() {
getline(cin, input);
getline(cin, sub);
for (int i = 0; i < sub.length(); i++)
myHash[sub[i]]++;
for (int i = 0; i < input.size(); i++) {
if (myHash[input[i]] != 0)continue;
else printf("%c", input[i]);
}
printf("\n");
return 0;
}
哈希+映射字母
1084
//1.char和string进行大小写转换的思路:
//char: 直接加减32, 即'a'-'A'即可
//string: 使用<algorithm>transform(str.begin(), str.end(), ::toupper)函数
//2.思路: !!!!公共映射字母表(看到查找缺失字母就联想到这个)
//3.关于ASCII表的总结:
//(1)表长128
//(2)'0'--48
// (3)'9'--57
//(4)'A'--65
//(5)'a'--97
//测试做的时候被字母大小写转换挡了很久, 并没有想好题目的逻辑的秘密
#include <cstdio>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
vector<int>flag(200,0);
int main() {
string str1, str2;
cin >> str1 >> str2;
for (int i = 0; i < str2.size(); i++) {
if (str2[i] >= 'a'&&str2[i] <= 'z')str2[i] -= 32;
flag[str2[i]] = 1;
}
for (int i = 0; i < str1.size(); i++) {
if (str1[i] >= 'a'&&str1[i] <= 'z')str1[i] -= 32;
if (flag[str1[i]] == 0) {
flag[str1[i]] = 1;
printf("%c", str1[i]);
}
}
return 0;
}
哈希+映射字母+加减计数
1092
//核心: 字母哈希
// (1)大小为: 256
// (2)甚至不用char转int: int()
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <cmath>
using namespace std;
vector<int>myHash(256, 0);
int main(){
string shop, customer;
cin >> shop >> customer;
for (int i = 0; i < shop.length(); i++)myHash[shop[i]]++; //就当初始化为零
for (int i = 0; i < customer.length(); i++)myHash[customer[i]]--;
int useless = 0, use = 0;
for(int i=0;i<myHash.size();i++){
if (myHash[i] > 0)useless+=myHash[i];
else if (myHash[i] < 0)use+=abs(myHash[i]);
}
if (use == 0) printf("Yes %d\n", useless);
else printf("No %d\n", use);
return 0;
}
哈希+映射字母
1112
//1.核心: 字符哈希。
// (1)hash的大小是128
// (2)可开多个, 灵活使用, 以满足题目要求的条件
//2.当出现大量WA的时候应该思考的东西:
// (1)代码中应该使用变量的内容, 因为样例使用了常量
//3.当出现某个WA, 或者莫名其妙PE的时候:
// (1)尝试特殊样例
// (2)尝试边界样例
// (3)应该当, 尝试样例是很愉快的事情, 因为改动这样的代码是很简单的事情
//4.记录字符串某个连续子串的长度: 用rank的逻辑和代码块即可(i+1方法处理上一个 和 下一个关系还是好用的)
//5.for循环中也可以, 对i进行处理, 以配合逻辑。 尤其字符串等题目中
#include <iostream>
#include <vector>
#include <string>
using namespace std;
const int MAX = 128;
int k;
vector<int>yesHash(MAX, 0), noHash(MAX, 0), alreadyHash(MAX,0);
vector<char>results;
int main() {
scanf("%d", &k);
string str;
cin >> str;
int cnt = 0;
for (int i = 0; i < str.length(); i++) {
cnt++;
if ((i != (str.length() - 1) && ((str[i] != str[i + 1])||cnt==k))||(i==str.length()-1&&(cnt==k))) {
if (cnt == k && (noHash[str[i]]==0))yesHash[str[i]] = 1;
else if(cnt != k){
noHash[str[i]] = 1;
yesHash[str[i]] = 0;
}
cnt = 0;
}
}
//for (int i = 0; i < yesHash.size(); i++)printf("#%d", yesHash[i]);
for (int i = 0; i < str.length(); i++) {
if (yesHash[str[i]] && alreadyHash[str[i]] == 0) {
results.push_back(str[i]);
alreadyHash[str[i]] = 1;
}
}
for (int i = 0; i < results.size(); i++)printf("%c", results[i]);
printf("\n");
for (int i = 0; i < str.length(); i++) {
printf("%c", str[i]);
if (yesHash[str[i]])i += (k-1);
}
printf("\n");
return 0;
}
哈希+插入+二次方探查
1078
//二次方探查:index(input+i*i)%size (其中0<= i <= m)
//hash:
// (1)首先: 会让你寻找tablesize----while(!isPrime(size))size++;
// (2)其次: 大循环输入
// (3)然后: 小循环二次方探查
// (4)最后: 不冲突插入
#include <cstdio>
#include <vector>
using namespace std;
vector<int>hashTable;
bool isPrime(int x) {
if (x <= 1)return false;
for (int i = 2; i*i <= x; i++)
if (x%i == 0)return false;
return true;
}
int main() {
int m, n, tmp, index,ans;
scanf("%d %d",&m ,&n);
while (!isPrime(m))m++;
hashTable.resize(m);
for (int i = 0; i < n; i++) {
scanf("%d", &tmp);
ans = -1;
for (int j = 0; j <= m ; j++) {
index = (tmp + j * j) % m;
if (!hashTable[index]) {
hashTable[index] = tmp;
ans = index;
break;
}
}
if (i)printf(" ");
if (ans == -1) printf("-");
else printf("%d", ans);
}
return 0;
}
哈希+插入+查找计数+二次方探查
1145
//二次方探查:index(input+i*i)%size (其中0<= i <= m) 二次方探查的次数一定是【0,size】闭区间
//hash插入:
// (1)首先: 会让你寻找tablesize----while(!isPrime(size))size++;
// (2)其次: 大循环输入
// (3)然后: 小循环二次方探查
// (4)最后: 不冲突插入
//hash查找:
// (1)小循环二次方探查: cnt++
// 1)==0或==x: return
// 2)!=x: continue
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
vector<int>hashTable;
int times=0, mSize;
bool isPrime(int x) {
if (x <= 1)return false;
for (int i = 2; i*i <= x; i++)
if (x%i == 0)return false;
return true;
}
bool insert(int x) {
for (int i = 0; i <= mSize; i++) {
int index = (x + i * i) % mSize;
if (hashTable[index]==0) {
hashTable[index]=x;
return true;
}
}
return false; //之前还在思考这里的逻辑, 其实直接就好(不是true就是flase)
}
void search(int x) {
for (int i = 0; i <= mSize; i++) {
int index = (x + i * i) % mSize;
times++;
if (hashTable[index] == 0||(hashTable[index]==x))return;
else if(hashTable[index]!=x)continue;
}
}
int main() {
int n, m, input;
scanf("%d %d %d", &mSize, &n, &m);
while (!isPrime(mSize))mSize++;
hashTable.resize(mSize);
fill(hashTable.begin(), hashTable.end(), 0);
for (int i = 0; i < n; i++) {
scanf("%d", &input);
if (!insert(input))printf("%d cannot be inserted.\n", input);
}
for (int i = 0; i < m; i++) {
scanf("%d", &input);
search(input);
}
printf("%.1f", times*1.0/m);
return 0;
}
哈希+两数和为定值(凑硬币面值)
1048
//核心: 用已有东西凑出某样东西----哈希表正合适
#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
int n, m;
map<int, int>myHash;
int main() {
scanf("%d %d", &n, &m);
for (int i = 0; i < n; i++) {
int tmp;
scanf("%d", &tmp);
myHash[tmp]++;
}
int a,b;
map<int, int>::iterator it;
for (it = myHash.begin(); it != myHash.end(); it++) {
it->second--;
if (myHash.find(m - it->first) != myHash.end()&&(myHash[m-it->first]!=0)) {
a = it->first;
b = m - it->first;
break;
}
}
if (it == myHash.end())printf("No Solution\n");
else printf("%d %d\n", a, b);
return 0;
}
哈希+一些元素是否包含一组特定元素
1134
//思路: 一开始还是没想到怎么用hash
// (1)按照输入下标, 给每条边编号, 形成hash表
// (2)处理每个节点关联的边
// (3)最后,看hash表中元素是否全都遇到过
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
vector<vector<int> >edges;
vector<int>hashTable;
int main() {
int n, m, query;
scanf("%d %d", &n, &m);
edges.resize(n);
hashTable.resize(m);
fill(hashTable.begin(), hashTable.end(), 0);
for (int i = 0; i < m; i++) {
int a, b;
scanf("%d %d", &a, &b);
edges[a].push_back(i);
edges[b].push_back(i);
}
scanf("%d", &query);
for (int i = 0; i < query; i++) {
fill(hashTable.begin(), hashTable.end(), 0);
int k, input, flag=0;
scanf("%d", &k);
for (int j = 0; j < k; j++) {
scanf("%d", &input);
for (int t = 0; t < edges[input].size(); t++)hashTable[edges[input][t]] = 1;
}
for(int j=0;j<hashTable.size();j++)
if (hashTable[j] == 0) {
flag = 1;
break;
}
if (flag)printf("No\n");
else printf("Yes\n");
}
return 0;
}