第九章 哈希

1048.找硬币

在这里插入图片描述

1063.集合相似度

在这里插入图片描述

  • Nc=两个集合中不同元素的数量,Nt=集合A的元素数量+集合B的元素数量-NC
#include<iostream>
#include<algorithm>
#include<unordered_map>

using namespace std;

const int N=60;

unordered_map <int,int> has[N];

int n,k;

double check(int a,int b){
    
    int diff=0,sum=0;
    
    for(auto it :has[a])
        
        if(has[b].count(it.first))diff++;
  
    sum=has[a].size()+has[b].size()-diff;
    
    return (double)diff/sum;
}

int main(){
    
    cin>>n;
    
    for(int i=1;i<=n;i++){
        
        int m;
        
        cin>>m;
        
        while(m--){
            
            int x;
            
            cin>>x;
            
            has[i][x]++;
        }
    }
    
    cin>>k;
    
    while(k--){
        
        int a,b;
        
        cin>>a>>b;
        
        double res=check(a,b);
        
        printf("%.1lf%%\n",res*100);
    }
}


1120.朋友数

在这里插入图片描述


#include<iostream>
#include<algorithm>
#include<set>
#include<vector>

using namespace std;

int count(int x){
    
    int res=0;
    
    while(x)res+=x%10,x/=10;
    
    return res;
}

int main(){
    
    int n;
    
    cin>>n;
    
    set<int> S;
    
    while(n--){
        
        int x;
        
        cin>>x;
        
        S.insert(count(x));
    }
    
    cout<<S.size()<<endl;
    
    bool is_first=true;
    
    for(auto it : S){
        
        if(is_first)is_first=false;
        
        else cout<<" ";
        
        cout<<it;
    }
    
    
}

1144.漏掉的数字

在这里插入图片描述

#include<iostream>
#include<set>

using namespace std;

int n;

int main(){
    
    cin>>n;
    
    set<int> S;
    
    while(n--){
        
        int x;
        
        cin>>x;
        
        if(x>0)S.insert(x);
    }
    
    int min=1;
    
    for(auto x : S){
        
        if(x==min)min++;
        
        else break;
    }
    
    cout<<min;
    
}

1149.危险品装箱

在这里插入图片描述

  • 时间复杂度足够,不用建图
#include<iostream>
#include<algorithm>
#include<unordered_map>
#include<unordered_set>

using namespace std;

const int N=1e4+10;

int n,m;

int a[N],b[N];
    
bool check(unordered_set<int> S){
    
    for(int i=0;i<n;i++){
        
        if(S.count(a[i]) && S.count(b[i]))return false;
    }
    
    return true;
}

int main(){
    
    cin>>n>>m;
    
    for(int i=0;i<n;i++)cin>>a[i]>>b[i];
    
    while(m--){
        
        int k;
        
        cin>>k;
        
        unordered_set<int> S;
        
        while(k--){
            
            int x;
            
            cin>>x;
            
            S.insert(x);
        }
        
        if(check(S))cout<<"Yes"<<endl;
        
        else cout<<"No"<<endl;
    }
}


1078.哈希 *

在这里插入图片描述

  • 本题注意二次增量探测法的定义
  • 二次增量探测法: 哈希表长S,当前数x,则插入位置pos=(x+i*i)%S,(i=0,1,2,3....S)
#include<iostream>
#include<algorithm>
#include<unordered_set>

using namespace std;

const int N=1e4+10;

int m,n;
    
unordered_set<int> S;

bool check(int x){
    
    if(x==1)return true;    //1不是质数
    
    for(int i=2;i<=x/i;i++){
        
        if(x%i==0)return true;
    }
    
     return false;
}

int find(int x){
    
    for(int i=0;i<m;i++){         //找到可以插入的位置
        
        int pos = (x+i*i)%m;
        
        if(!S.count(pos)){
            
            S.insert(pos);
            
            return pos;
        }
    }
    
    return -1;                  //找不到返回-1
}

int main(){
    
    cin>>m>>n;

    while(check(m))m++;
    
    bool is_first=true;
    
    for(int i=0;i<n;i++){
        
        int x;
        
        cin>>x;
        
        int pos=find(x);
        
        if(is_first)is_first=false;
        
        else cout<<" ";
        
        if(pos==-1)cout<<"-";
        
        else cout<<pos;
    }
}

1137.期终成绩

在这里插入图片描述

#include<iostream>
#include<algorithm>
#include<unordered_map>
#include<vector>
#include<cmath>
#include<cstring>

using namespace std;

struct Student {
    
    string id;
    
    int p,m,f,s;           //编程分数,期中成绩,期末成绩,总成绩
    
    Student(): p(-1),m(-1),f(-1),s(0) {}
    
    void cal(){
        
        if(f>=m)s=f;
        
        else s=round(m*0.4+f*0.6);    //四舍五入
    }
    
    bool operator < (const Student & t) const {
        
        if(s!=t.s)return s>t.s;
        
        else return id<t.id;
    }
};



int main(){
    
    int P,M,N;
    
    cin>>P>>M>>N;
    
    string id;
    
    int score;
    
    unordered_map<string,Student> has;
    
    for(int i=0;i<P;i++){
        
        cin>>id>>score;
        
        has[id].id=id;
        
        has[id].p=score;
    }
    
    for(int i=0;i<M;i++){
        
        cin>>id>>score;
        
        has[id].id=id;
        
        has[id].m=score;
    }
    
    for(int i=0;i<N;i++){
        
        cin>>id>>score;
        
        has[id].id=id;
        
        has[id].f=score;
    }
    
    vector<Student> res;
    
    for(auto item : has){
        
        auto stu =item.second;
        
        stu.cal();
        
        if(stu.p>=200 && stu.s>=60)res.push_back(stu);
    }
    
    sort(res.begin(),res.end());
    
    for(auto it : res){
        
        cout<<it.id<<" "<<it.p<<" "<<it.m<<" "<<it.f<<" "<<it.s<<endl;
    }
}

1645.哈希-平均查找时间

在这里插入图片描述


#include <iostream>

using namespace std;

const int N = 10010;

int s, n, m;
int h[N];

bool is_prime(int x)
{
    if (x == 1) return false;

    for (int i = 2; i * i <= x; i ++ )
        if (x % i == 0)
            return false;

    return true;
}

int find(int x, int &cnt)
{
    int t = x % s;

    cnt = 1;
    for (int k = 0; k < s; k ++, cnt ++ )
    {
        int i = (t + k * k) % s;
        if (!h[i] || h[i] == x) return i;
    }

    return -1;
}

int main()
{
    cin >> s >> n >> m;

    while (!is_prime(s)) s ++ ;

    for (int i = 0; i < n; i ++ )
    {
        int x, count;
        cin >> x;

        int t = find(x, count);
        if (t == -1) printf("%d cannot be inserted.\n", x);
        else h[t] = x;
    }

    int cnt = 0;
    for (int i = 0; i < m; i ++ )
    {
        int x, count;
        cin >> x;
        find(x, count);
        cnt += count;
    }

    printf("%.1lf\n", (double)cnt / m);

    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值