散列
导入:
有N个数和M个数,如何判断M个数中每个数是否在N中出现?
思想:空间换时间
创建hashtable,以N个数本身为索引(数组下标)构建 bool hashtable
输入x的过程中,hashtable[x]=True(若要计算出现次数,换成++)
但终归是有局限性!数字只能是整数,还不能太大,等等。
散列函数:平房区中法、取余数……
可能会冲突:(即:不是单射了)
字符串哈希:借鉴26进制的推广:62进制
字符是否出现
如何判断输完了?
本地devc++我可以说:c1!='\n',c1!=' ','a'<=c1<='z'都能跑,如
#include<stdio.h>
#include<string>
using namespace std;
int main()
{
printf("%d",'\n'>='a');
// char c1[27];
char c1;
char c2[27]={0};
int i=0;
scanf("%c",&c1);
while(c1>='a'&&c1<='z')
{
c2[c1-'a']++;
scanf("%c",&c1);
}
for(int j=0;j<26;j++)
if(c2[j]>0) printf("%c %d\n",'a'+j,c2[j]);
}
然而网站上不行,得用while(scanf("%c",&c1)!=EOF)
#include<stdio.h>
#include<string>
using namespace std;
int main()
{
// char c1[27];
char c1;
char c2[27]={0};
int i=0;
// scanf("%c",&c1);
while(scanf("%c",&c1)!=EOF)
{
c2[c1-'a']++;
// scanf("%c",&c1);
}
for(int j=0;j<26;j++)
if(c2[j]>0) printf("%c %d\n",'a'+j,c2[j]);
}
这个本地不能跑了。。
行吧,得改头换面用cstring
字符出现次数
这里我忘了这个:
就算你定义char a[1000],如果赋值“avx”,仍然可以使用长度strlen,仍为3
我的代码
#include<stdio.h>
#include<cstring>
using namespace std;
int main()
{
char s1[1001],s2[1001];
int s[26]={0};
scanf("%s",&s1);scanf("%s",&s2);
for(int i=0;s1[i]>='a'&&s1[i]<='z'&&i<1001;i++)
s[s1[i]-'a']=1;
for(int i=0;s2[i]>='a'&&s2[i]<='z'&&i<1001;i++)
{
if(i==0) printf("%d",s[s2[i]-'a']);
else printf(" %d",s[s2[i]-'a']);
}
}
答案
#include <cstdio>
#include <cstring>
const int MAXN = 26;
const int MAXL = 1001;
char str1[MAXL], str2[MAXL];
bool hashTable[MAXN] = {false};
int getHashKey(char c) {
return c - 'a';
}
int main () {
scanf("%s%s", str1, str2);
int len1 = strlen(str1);
int len2 = strlen(str2);
for (int i = 0; i < len1; i++) {
hashTable[getHashKey(str1[i])] = true;
}
for (int i = 0; i < len2; i++) {
printf("%d", hashTable[getHashKey(str2[i])]);
printf(i < len2 - 1 ? " " : "\n");
}
return 0;
}
力扣经典题:两数之和
简单版
我的代码(devc++int数组长度设为1000000报错,但是网上通过了)
#include<stdio.h>
#include<cstring>
using namespace std;
int main()
{
int n,k;
scanf("%d %d",&n,&k);
int A[n];
int h[1000000]={0};
int ans=0;
int a0=0;
for(int i=0;i<n;i++)
{
scanf("%d",&a0);
A[i]=a0;
h[A[i]]++;
}
for(int i=0;i<n;i++)
{
if(k>=A[i])
{
if(A[i]<=k-A[i])
{
if(A[i]==k-A[i])
{
if(h[A[i]]>1)
ans++;//printf("-%d-",A[i]);
}
else if(h[k-A[i]]>0) ans++;//printf("-%d-",A[i]);
}
else break;
}
}
printf("%d",ans);
}
答案(他是遍历整个,再除以二)
#include <cstdio>
const int MAXN = 100000;
const int MAXK = 1000001;
int a[MAXN], hashTable[MAXK] = {false};
int main () {
int n, k;
scanf("%d%d", &n, &k);
for (int i = 0; i < n; i++) {
scanf("%d", &a[i]);
hashTable[a[i]] = true;
}
int ans = 0;
for (int i = 0; i < n; i++) {
if (k - a[i] >= 0 && hashTable[k - a[i]]) {
ans++;
}
}
printf("%d", ans / 2);
return 0;
}
集合运算
交
思路:第一个数组构造哈希表,然后遍历第二个,输出值为1者
数组长度10001错误,数组长度20000,通过。。
#include<stdio.h>
#include<cstring>
using namespace std;
int main()
{
int n1,n2;
scanf("%d %d",&n1,&n2);
int A[n1],B[n2],h1[20010],h2[20010];
int a0=0;
for(int i=0;i<n1;i++)
{
scanf("%d",&a0);
A[i]=a0;
h1[A[i]]++;
}
bool flag=0;
for(int i=0;i<n2;i++)
{
scanf("%d",&a0);
B[i]=a0;
//求交集:
if(h1[a0])
{
if(flag) printf(" %d",a0);
else printf("%d",a0);
flag=1;
}
// h2[B[i]]++;
}
}
并
思路:遍历第一个数组构造哈希表,然后遍历第二个,把第一个为0的但第二个出现的数字的哈希值改为1,最后遍历整个表,输出值为1的
#include<stdio.h>
#include<cstring>
using namespace std;
int main()
{
int n1,n2;
scanf("%d %d",&n1,&n2);
int A[n1],B[n2],h1[20000]={0},h2[20000]={0};
int a0=0;
for(int i=0;i<n1;i++)
{
scanf("%d",&a0);
A[i]=a0;
h1[A[i]]++;
}
bool flag=0;
for(int i=0;i<n2;i++)
{
scanf("%d",&a0);
B[i]=a0;
//求交集:
// if(h1[a0])
// {
// if(flag) printf(" %d",a0);
// else printf("%d",a0);
// flag=1;
// }
//并集
if(!h1[a0]) h1[a0]++;
}
//并集:整个儿遍历10000?
for(int i=0;i<20000;i++)
if (h1[i])
{if(flag) printf(" %d",i);
else printf("%d",i);
flag=1;
}
}
差
思路:遍历第一个造出哈希表,遍历第二个,每找一个,哈希表对应值-1;最后遍历第一个集合,每输出一次,哈希值-1,直至为0
#include<stdio.h>
#include<cstring>
using namespace std;
int main()
{
int n1,n2;
scanf("%d %d",&n1,&n2);
int A[n1],B[n2],h1[20000]={0},h2[20000]={0};
int a0=0;
for(int i=0;i<n1;i++)
{
scanf("%d",&a0);
A[i]=a0;
h1[A[i]]++;
}
bool flag=0;
for(int i=0;i<n2;i++)
{
scanf("%d",&a0);
B[i]=a0;
//求差集
if(h1[a0]) h1[a0]--;
}
for(int i=0;i<n1;i++)
{
while(h1[A[i]])
{
if(flag) printf(" %d",A[i]);
else printf("%d",A[i]);
flag=1;
h1[A[i]]--;
}
}
}
//求交集:
// if(h1[a0])
// {
// if(flag) printf(" %d",a0);
// else printf("%d",a0);
// flag=1;
// }
//并集
// if(!h1[a0]) h1[a0]++;
//}
//并集:整个儿遍历10000?
//for(int i=0;i<20000;i++)
//if (h1[i])
//{if(flag) printf(" %d",i);
// else printf("%d",i);
// flag=1;
// }
字符串的出现次数
我:
#include<stdio.h>
#include<cstring>
using namespace std;
int abc(char str[4])
{
return (str[0]-'A')*26*26+(str[1]-'A')*26+(str[2]-'A');
}
int main()
{
int n1,n2;
scanf("%d",&n1);
char s1[n1+1][5];
int si1[20000]={0};
for(int i=0;i<n1;i++)
{
scanf("%s",s1[i]);
// printf("%d",abc(s1[i]));
si1[abc(s1[i])]++;
// printf("%s&%d",s1[i],si1[abc(s1[i])]);
}
scanf("%d",&n2);
char s2[n2+1][5];
for(int i=0;i<n2;i++)
{
scanf("%s",s2[i]);
if (si1[abc(s2[i])]) printf("%d",si1[abc(s2[i])]);
else printf("0");
if (i<n2-1) printf(" ");
}
//COD
//ABA
}
答案
#include <cstdio>
const int MAXN = 26 * 26 * 26;
const int MAXL = 1001;
char str[MAXL];
int hashTable[MAXN] = {0};
int getHashKey(char s[]) {
return (s[0] - 'A') * 26 * 26 + (s[1] - 'A') * 26 + (s[2] - 'A');
}
int main () {
int n, m;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%s", str);
hashTable[getHashKey(str)]++;
}
scanf("%d", &m);
for (int i = 0; i < m; i++) {
scanf("%s", str);
printf("%d", hashTable[getHashKey(str)]);
printf(i < m - 1 ? " " : "\n");
}
return 0;}
标签:练习题,26,int,scanf,char,哈希,c1,include,散列 From: https://blog.csdn.net/m0_68339197/article/details/139183886