zoukankan      html  css  js  c++  java
  • PAT (Advanced Level) 1144~1147:1145Hash二次探查 1146拓扑排序 1147堆

    1144 The Missing Number(20 分)

    题意:给定N个数的序列,输出不在序列中的最小的正整数。

    分析:

    1、给定的N个数可能为正,可能为负,可能重复。

    2、由于N105​​,所以,当N个数互不重复,且都为正的情况下,所输出的数最大,为105​​+1。

    3、将序列中的数标注后,枚举1~105​​+1,遇到的第一个未标注的数即为答案。

    4、注意标注序列中的数时,大于105​​+1的数没必要标注(因为给定的数在int范围内),否则会下标越界。

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<iostream>
    using namespace std;
    const int MAXN = 100000 + 10;
    int a[MAXN];
    bool vis[MAXN];
    int main(){
        int N;
        while(scanf("%d", &N) == 1){
            memset(vis, false, sizeof vis);
            for(int i = 0; i < N; ++i){
                scanf("%d", &a[i]);
                if(a[i] > 0 && a[i] < MAXN) vis[a[i]] = true;
            }
            for(int i = 1; i < MAXN; ++i){
                if(!vis[i]){
                    printf("%d", i);
                    break;
                }
            }
        }
        return 0;
    }
    

    1145 Hashing - Average Search Time(25 分)

    题意:给定N个数,插入到长度为MSize的哈希表中,计算查找M个数的平均查找时间。

    分析:

    1、哈希函数:H(key)=key%MSize

    2、题目中要求通过二次探查法解决冲突,且只考虑正增量。

    (1)二次探查法的探查序列为Hi=(H(key)+i)%MSize,i取值依次为1*1,-1*1,2*2,-2*2,3*3,-3*3,...,(MSize-1)*(MSize-1),-(MSize-1)*(MSize-1)

    (2)由于只考虑正增量,所以i取值为1*1,2*2,3*3,...,(MSize-1)*(MSize-1)
    (3)对于i依次取值来解决冲突,如果所有的取值都冲突,则插入失败。
    3、查询某数时所执行的操作与插入操作相同,如果查询到的位置为空,则表示该数字不在Hash表中;如果遍历所有的i都未找到,则查询总数加1。
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<iostream>
    #include<map>
    #include<queue>
    #include<vector>
    #include<cmath>
    using namespace std;
    const int MAXN = 10000 + 10;
    int MSize, N, M;
    int Hash[MAXN];
    bool judge_prime(int x){
        if(x <= 1) return false;
        for(int i = 2; i <= (int)(sqrt(x + 0.5)) + 1; ++i){
            if(x % i == 0) return false;
        }
        return true;
    }
    int main(){
        while(scanf("%d%d%d", &MSize, &N, &M) == 3){
            memset(Hash, -1, sizeof Hash);
            while(!judge_prime(MSize)) ++MSize;
            int key;
            while(N--){
                scanf("%d", &key);
                int Hkey = key % MSize;
                bool ok = false;
                if(Hash[Hkey] == -1){
                    Hash[Hkey] = key;
                    ok = true;
                }
                else{
                    for(int i = 1; i <= MSize - 1; ++i){
                        int tmp = (Hkey + i * i) % MSize;
                        if(Hash[tmp] == -1){
                            Hash[tmp] = key;
                            ok = true;
                            break;
                        }
                    }
                }
                if(!ok) printf("%d cannot be inserted.
    ", key);
            }
            int x;
            int sum = 0;
            for(int i = 0; i < M; ++i){
                scanf("%d", &x);
                int Hkey = x % MSize;
                bool ok = false;
                for(int j = 0; j < MSize; ++j){
                    int tmp = (Hkey + j * j) % MSize;
                    ++sum;
                    if(Hash[tmp] == -1 || Hash[tmp] == x){
                        ok = true;
                        break;
                    }
                }
                if(!ok) ++sum;
            }
            printf("%.1lf
    ", sum * 1.0 / M);
        }
        return 0;
    }

    1146 Topological Order(25 分)

    题意:给定一个有向图,判断所给的K个选项中哪个不是该图的拓扑排序。

    分析:

    1、遍历所给的拓扑序,边遍历边将该点所指向的点入度-1。

    2、在进行上述操作的前提下,如果遍历到的每个点入度都为0,则该序列一定是拓扑序。

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<iostream>
    #include<map>
    #include<queue>
    #include<vector>
    using namespace std;
    const int MAXN = 1000 + 10;
    vector<int> G[MAXN];
    int indegree[MAXN];
    int tmpindegree[MAXN];
    vector<int> ans;
    vector<int> v;
    int N, M;
    void init(){
        for(int i = 1; i <= N; ++i) G[i].clear();
        memset(indegree, 0, sizeof indegree);
        ans.clear();
    }
    bool judge(){//判断是否为拓扑序列
        int len = v.size();
        for(int i = 0; i < len; ++i){
            int cur = v[i];
            if(!tmpindegree[cur]){
                int l = G[cur].size();
                for(int j = 0; j < l; ++j){
                    --tmpindegree[G[cur][j]];
                }
            }
            else return false;
        }
        return true;
    }
    int main(){
        while(scanf("%d%d", &N, &M) == 2){
            init();
            int st, ed;
            for(int i = 0; i < M; ++i){
                scanf("%d%d", &st, &ed);
                G[st].push_back(ed);
                ++indegree[ed];
            }
            int K, x;
            scanf("%d", &K);
            for(int i = 0; i < K; ++i){
                memcpy(tmpindegree, indegree, sizeof indegree);
                v.clear();
                for(int j = 0; j < N; ++j){
                    scanf("%d", &x);
                    v.push_back(x);
                }
                if(!judge()) ans.push_back(i);
            }
            int len = ans.size();
            for(int i = 0; i < len; ++i){
                if(i) printf(" ");
                printf("%d", ans[i]);
            }
            printf("
    ");
        }
        return 0;
    }
    

    1147 Heaps(30 分)

    题意:给定一个完全二叉树的层次遍历序列,问该二叉树是否为堆结构,并进一步判断是大顶堆还是小顶堆,最后输出该二叉树的后序遍历序列。

    分析:

    1、由于给定的N (1<N≤1000)个点数字各不相同,且大小都在int范围内,首先对N个点进行坐标离散化。

    2、利用queue边读取边判断该二叉树是否为堆结构,同时记录每个点的左右子结点。

    3、进行后序遍历。

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<iostream>
    #include<map>
    #include<queue>
    using namespace std;
    const int MAXN = 100000 + 10;
    int lchild[MAXN], rchild[MAXN];
    map<int, int> mp1;
    map<int, int> mp2;
    queue<int> q;
    vector<int> ans;
    int root;
    int cnt;
    void init(){
        memset(lchild, 0, sizeof lchild);
        memset(rchild, 0, sizeof rchild);
        mp1.clear();
        mp2.clear();
        while(!q.empty()) q.pop();
        ans.clear();
    }
    void get_id(int x){//坐标离散化
        ++cnt;
        mp1[x] = cnt;
        mp2[cnt] = x;
    }
    int judge(int type_l, int type_r){
        if(type_l == 1 && type_r != 2){
            return 1;//Min Heap
        }
        else if(type_l == 2 && type_r != 1){
            return 2;//Max Heap
        }
        else{
            return 3;
        }
    }
    void print_postorder(int x){
        if(lchild[x]) print_postorder(lchild[x]);
        if(rchild[x]) print_postorder(rchild[x]);
        ans.push_back(mp2[x]);
    }
    int main(){
        int M, N;
        while(scanf("%d%d", &M, &N) == 2){
            while(M--){
                init();
                cnt = 0;
                int x;
                scanf("%d", &x);
                q.push(x);
                get_id(x);
                root = mp1[x];
                int type = 0;
                bool ok = true;
                while(!q.empty()){
                    int top = q.front();
                    q.pop();
                    int type_l = 0;
                    int type_r = 0;
                    if(cnt < N){
                        scanf("%d", &x);
                        get_id(x);
                        lchild[mp1[top]] = mp1[x];
                        q.push(x);
                        if(top < x) type_l = 1;
                        else type_l = 2;
                    }
                    if(cnt < N){
                        scanf("%d", &x);
                        get_id(x);
                        rchild[mp1[top]] = mp1[x];
                        q.push(x);
                        if(top < x) type_r = 1;
                        else type_r = 2;
                    }
                    if(type == 0) type = judge(type_l, type_r);
                    else{
                        int tmptype = judge(type_l, type_r);
                        if(tmptype != type || type == 3) ok = false;
                    }
                    if(cnt == N) break;
                }
                if(!ok) printf("Not Heap
    ");
                else{
                    if(type == 1) printf("Min Heap
    ");
                    else printf("Max Heap
    ");
                }
                print_postorder(root);
                int len = ans.size();
                for(int i = 0; i < len; ++i){
                    if(i) printf(" ");
                    printf("%d", ans[i]);
                }
                printf("
    ");
            }
        }
        return 0;
    }
    
  • 相关阅读:
    [JSOI2015]最小表示
    [洛谷2002]消息扩散
    [洛谷1726]上白泽慧音
    [CodeVS2822]爱在心中
    [POJ2186]Popular Cows
    [洛谷1991]无线通讯网
    [CQOI2009]跳舞
    [洛谷1342]请柬
    [USACO07JAN]Balanced Lineup
    [NOIp2003提高组]神经网络
  • 原文地址:https://www.cnblogs.com/tyty-Somnuspoppy/p/9482988.html
Copyright © 2011-2022 走看看