PAT-哈希表(AcWingPAT甲级课笔记)

目录

1048 Find Coins

1063 Set Similarity

1120 Friend Numbers

1144 The Missing Number

1149 Dangerous Goods Packaging

1078 Hashing

1145 Hashing - Average Search Time

1137 Final Grading


1048 Find Coins

解析

法一:hash表

1.用一个哈希表存储硬币,对于每一枚硬币 x,判断在集合中是否存在 y,使得 x + y = m。

2.如果存在,则是一组解,判断该解的小面值硬币是否小于 v1, 如果是,则存入 v1, v2。

如果存在解,则输出。否则无解。

注意点

先判断再插入,效率比较高

#include <iostream>
#include <unordered_set>

using namespace std;

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

    unordered_set<int> S; //存储数据的哈希表
    int v1 = 1e9, v2; //v1 设置一个较大的值
    for (int i = 0; i < n; i ++ ){
        int x;
        cin >> x;
        int y = m - x; //x + y = m,对于输入的 x,在堆中查看有没有 y。 
        if (S.count(y)){
            S.insert(x);
            if (x > y) swap(x, y);
            if (x < v1) v1 = x, v2 = y;  //判断该解的小面值是否小于 v1,如果是,则把该解存入 v1, v2.
        }
        else S.insert(x);
    }

    if (v1 == 1e9) puts("No Solution"); 
    else cout << v1 << ' ' << v2 << endl;

    return 0;
}

法二:双指针

解析

1.先排序
2.左指 l 针指向数组头,右指针 r 指向数组尾。
如果 a[l] + a[r] > m , 则 r 左移。
如果 a[l] + a[r] < m , 则 l 右移。
如果 a[l] + a[r] = m , 则找到解。
如果指针相遇还没有出现 a[l] + a[r] = m ,则无解。

注意点

#include<iostream>
#include<algorithm>

using namespace std;

const int N = 100010;
int ans[N];

int main(){
    int n, m;
    cin >> n >> m;
    int v1 = -1, v2 = -1;

    for(int i = 0; i < n; i++){
        int x;
        cin >> ans[i];
    }
    sort(ans, ans + n);  //双指针需要先排序

    int l = 0, r = n - 1; //l 左指针,r 右指针
    while(l < r){  //指针未相遇就一直执行
        if(ans[l] + ans[r] == m){   //找到答案
            v1 = ans[l];
            v2 = ans[r];
            break;
        }else if(ans[l] + ans[r] > m){ //两数之和大于 m, 则右指针左移
            r--;
        }else{  //两数之和小于 m, 则做指针右移
            l++;
        }
    }

    if(v1 >= 1){  //v1 大于 1 说明找到了解
        cout << v1 << " " << v2;
    }else{
        cout << "No Solution";
    }
    return 0;
}

1063 Set Similarity

解析:

Nc:两个集合交集的元素数量

Nt:两个集合并集的元素数量

注意点:最后输出% 要在printf里加两个%%

(double)nc / nt * 100

#include <iostream>
#include <unordered_set>

using namespace std;

const int N = 55;

int n;
unordered_set<int> S[N];

int main(){
    scanf("%d", &n);

    for (int i = 1; i <= n; i ++ ){
        int m;
        scanf("%d", &m);
        while (m -- ){
            int x;
            scanf("%d", &x);
            S[i].insert(x);
        }
    }

    int k;
    scanf("%d", &k);
    while (k -- ){
        int a, b;
        scanf("%d%d", &a, &b);
        int nc = 0;
        for (auto x : S[a]) nc += S[b].count(x);
        int nt = S[a].size() + S[b].size() - nc;
        printf("%.1lf%%\n", (double)nc / nt * 100);
    }

    return 0;
}

1120 Friend Numbers

注意点

1. 有顺序的输出,所以不用unordered_set

2.如何分解数的每一位, 高精度思想 

#include<iostream>
#include<set>

using namespace std;

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

    set<int> S;   //set自动排序
    while(n--){
        int x;
        cin >> x;
        int s = 0;
        while(x != 0) s += x % 10, x /= 10;  //如何分解每一位
        S.insert(s);
    }

    cout << S.size() << endl;
    
    bool flag = true;
    for(auto x : S){           
        if(flag) flag = false;   //如何处理最后多一个空格
        else cout << " ";
        cout << x;
    }

    return 0;
}

1144 The Missing Number

解析

注意点

1.最后一组数据 有个20000000 用数组当哈希表会出现段错误

#include <iostream>
#include <unordered_set>

using namespace std;

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

    unordered_set<int> S;
    while (n -- ){
        int x;
        cin >> x;
        S.insert(x);
    }

    int res = 1;
    while (S.count(res)) res ++ ;

    cout << res << endl;

    return 0;
}

用数组当哈希表

#include <iostream>

using namespace std;

const int N = 1e5 + 10;
int a[N] = {0};

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

    while(n--){
        int x;
        cin >> x;
        if(x > 0 && x < N){
            a[x]++;
        }
    }
    for(int i = 1; i < N; i++){
        if(a[i] == 0){
            cout << i;
            break;
        }
    }

    return 0;
}

1149 Dangerous Goods Packaging

解析

注意点

#include<iostream>
#include<cstring>
#include<unordered_set>

using namespace std;

#define x first  //把first定义为x
#define y second //把second定义为y

typedef pair<int,int> PII;  //出现一对的时候很好用
const int N = 10010;

PII a[N];

int main(){
    int n, m;
    cin >> n >> m;
    for(int i = 0; i < n; i ++){
        cin >> a[i].x >> a[i].y;
    }

    while(m--){
        unordered_set<int> S;
        int k; 
        cin >> k;
        for(int i = 0; i < k; i ++){
            int x; 
            cin >> x;
            S.insert(x);
        }
        bool flag = true;
        for(int i = 0; i < n; i ++){
            if(S.count(a[i].x) && S.count(a[i].y)){ //遍历每个限制对,看有没有出现其中的某一个
                flag = false;
                break;
            }
        }
        if(flag) cout << "Yes" << endl;
        else cout << "No" << endl;
    }
    return 0;
}

1078 Hashing

#include <iostream>

using namespace std;

const int N = 10010;

int s, n;
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 t = x % s;

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

    return -1;
}

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

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

    for (int i = 0; i < n; i ++ ){
        int x;
        cin >> x;
        int t = find(x);

        if (t == -1) printf("-");
        else{
            h[t] = x;
            printf("%d", t);
        }

        if (i != n - 1) printf(" ");
    }
    
    return 0;
}

1145 Hashing - Average Search Time

#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;
}

1137 Final Grading

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

using namespace std;

struct Student{
    string id;
    int p, m, f, s;

    Student(): p(-1), m(-1), f(-1), s(0) {}

    void calc(){
        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;
        return id < t.id;
    }
};

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

    unordered_map<string, Student> hash;
    string id;
    int s;
    for (int i = 0; i < p; i ++ ){
        cin >> id >> s;
        hash[id].id = id;
        hash[id].p = s;
    }

    for (int i = 0; i < m; i ++ ){
        cin >> id >> s;
        hash[id].id = id;
        hash[id].m = s;
    }

    for (int i = 0; i < n; i ++ ){
        cin >> id >> s;
        hash[id].id = id;
        hash[id].f = s;
    }

    vector<Student> students;
    for (auto item : hash){
        auto stu = item.second;

        stu.calc();
        if (stu.p >= 200 && stu.s >= 60)
            students.push_back(stu);
    }

    sort(students.begin(), students.end());

    for (auto s : students)
        cout << s.id << ' ' << s.p << ' ' << s.m << ' ' << s.f << ' ' << s.s << endl;

    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值