On Hash

一、最常用——恒等变换

题目描述

  N个读者依次编号为1,2,…,N,把M本书依次编号为1,2,…,M。同时,按照“臭味相投”的原则,和你喜欢读同一本书的人,就是你的潜在朋友。你现在的任务是从这份借阅记录中计算出每个人有几个潜在朋友。

输入格式

  每个案例第一行两个整数N,M,2 <= N ,M<= 200。接下来有N行,第i(i = 1,2,…,N)行每一行有一个数,表示读者i-1最喜欢的图书的编号P(1<=P<=M)。

输出格式

  每个案例包括N行,每行一个数,第i行的数表示读者i有几个潜在朋友。如果i和任何人都没有共同喜欢的书,则输出“BeiJu”(即悲剧,^ ^)。

代码

#include <iostream>

using namespace std;

int main()
{
    int n,m;

    while(scanf("%d %d",&n,&m)!=EOF){
    int stu[200];
    int book[200]={0};
    for(int i=0;i<n;i++){
        scanf("%d",&stu[i]);
        int temp = stu[i];
        book[temp] ++;
    }
    for(int i=0;i<n;i++){
        int temp = stu[i];
        if(book[temp]>1){
            printf("%d\n",book[temp]-1);
        }
        else{
            printf("BeiJu\n");
        }
    }
    }

    return 0;
}

PS:时间复杂度为O(n),其中book数组使用了恒等变换的思想。

 

二、容器的合理使用

  虽然在hash这块有很多算法能够使用,但是不能一昧地盲目套用,往往会事倍功半。这里重点注意map容器,往往能够很简单地解决统计问题。

下面以一个题为例。

题目描述

Being unique is so important to people on Mars that even their lottery is designed in a unique way. The rule of winning is simple: one bets on a number chosen from [1, 104]. The first one who bets on a unique number wins. For example, if there are 7 people betting on 5 31 5 88 67 88 17, then the second one who bets on 31 wins.

输入

Each input file contains one test case. Each case contains a line which begins with a positive integer N (<=105) and then followed by N bets. The numbers are separated by a space.

输出

For each test case, print the winning number in a line. If there is no winner, print "None" instead.
 
代码
第一次思路
#include <iostream>

using namespace std;

int main()
{
    int num;
    while(scanf("%d",&num)!=EOF){
        int a[10010]={0};
        int flag=0;
        int maxn = 0;
        int times =1;
        if(num==1){
            int temp;
            scanf("%d",&temp);
            printf("%d\n",temp);
            continue;
        }
        for(int i=0;i<num;i++){
            int temp;
            scanf("%d",&temp);

            a[temp] ++;
            maxn = maxn>temp? maxn:temp;
            if(a[temp]>1){
                a[temp] = 0;
            }
            else{
                a[temp] = times;
                times++;
            }
        }
        int mark;
        int minn = times;
        for(int i=0;i<maxn;i++){
            if(a[i]<=minn&&a[i]>0){
                minn = a[i];
                mark=i;
                flag=1;
            }
        }
        if(flag==0) printf("None\n");
        else printf("%d\n",mark);
    }
    return 0;
}

改进思路:

#include <iostream>
#include <vector>
#include <unordered_map>
#include <cstdio>
using namespace std;

int main(){

    int num;
    while(scanf("%d",&num)!=EOF){
        int flag=0;
        vector<int> seq;
        unordered_map<int,int> nlog;
        for(int i=0;i<num;i++){
            int temp;
            scanf("%d",&temp);
            nlog[temp] ++;
            seq.push_back(temp);
        }
        for(vector<int>::iterator it=seq.begin();it!=seq.end();it++){
            if(nlog[*it]==1){
                printf("%d\n",*it);
                flag=1;
                break;
            }
        }
        if(flag==0) printf("None\n");
    }
}

孰简孰繁一目了然。

posted @ 2021-03-10 15:49  徐不二  阅读(30)  评论(0)    收藏  举报