算法学习——哈希

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Marilynmontu/article/details/82051901

散列(hash)是常用的算法思想,一般来说,散列可以浓缩为一句话“将元素通过一个函数转换为整数,使得该整数可以尽量唯一地代表这个元素”。


问题 A: 谁是你的潜在朋友
时间限制: 1 Sec 内存限制: 32 MB

题目描述
“臭味相投”——这是我们描述朋友时喜欢用的词汇。两个人是朋友通常意味着他们存在着许多共同的兴趣。然而作为一个宅男,你发现自己与他人相互了解的机会 并不太多。幸运的是,你意外得到了一份北大图书馆的图书借阅记录,于是你挑灯熬夜地编程,想从中发现潜在的朋友。
首先你对借阅记录进行了一番整理,把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”(即悲剧,^ ^)

样例输入
4 5
2
3
2
1
样例输出
1
BeiJu
1
BeiJu

解题思路
(1)数组bookTable按顺序存储读者i最喜欢的图书的编号;
(2)数组hashTable计数最喜欢图书j的读者的人数;
(3)依次输出读者i最喜欢的图书编号的读者人数,若人数大于1,则潜在的朋友数为该人数减去1;若人数等于1,则没有潜在的朋友,输出“BeiJu”。

Submission

#include<stdio.h>
int main(){
    int i, m, n, x;
    while ( scanf("%d %d", &n, &m) != EOF){
        int hashTable[210] = {0};
        int bookTable[210] = {0};
        for ( i = 0; i < n; i++ ){
            scanf("%d", &x);
            bookTable[i] = x;
            hashTable[x]++;
        }
        for ( i = 0; i < n; i++ ){
            if ( hashTable[bookTable[i]] > 1 )
            printf("%d\n", hashTable[bookTable[i]]-1 );
            else 
            printf("BeiJu\n");
        }
    }
    return 0;
}    

问题 B: 分组统计
时间限制: 1 Sec 内存限制: 32 MB

题目描述
先输入一组数,然后输入其分组,按照分组统计出现次数并输出,参见样例。

输入
输入第一行表示样例数m,对于每个样例,第一行为数的个数n,接下来两行分别有n个数,第一行有n个数,第二行的n个数分别对应上一行每个数的分组,n不超过100。

输出
输出m行,格式参见样例,按从小到大排。

样例输入
1
7
3 2 3 8 8 2 3
1 2 3 2 1 3 1
样例输出
1={2=0,3=2,8=1}
2={2=1,3=0,8=1}
3={2=1,3=1,8=0}

解题思路
(1)假设分为 i=1….n组,第一行输入的数字成员为 j=1…m,则设置一个二维数组GroupTable[i][j]存放第i组的数字成员j的个数。
(2)输出时按从小到大,且需要输出每个分组中每个数字成员的个数,即使为0。因此设置一个数组ExitMem[1001]记录输入的数字成员的种类。输出的分组序号一定是包含数字成员的,设置一个数组NumTable[1001]记录每个分组数字成员的个数。
(3)为了减小循环次数,在输入数据时,通过比较得出最大的数字成员和最大的分组序号。
注意:由于把n<=100误认为是数字成员的范围导致输出超限,修改了输入输出方式(由printf和scanf改为cout和cin)且增大了数组的范围之后解决了这一问题。

Submission

#include<stdio.h>
#include<iostream>
using namespace std;
int main(){
    int i, j, m, n, x;
    cin >> m;
    while( m  != 0 ){
        int GroupTable[1001][1002] = {0}; //存放每个分组中的数对应的成员数字 
        int ExitMem[1001] = {0};//存放目前存在的成员数字的个数,便于后期输出
        int NumTable[1001] = {0}; //存放每个分组中的数的个数  
        int MemTable[1001] = {0}; //存放待分组的数 
        int group_num = 0;//存放分组的总数量 
        int max_group = 0;//存放最大的分组下标 
        int max_num = 0;//存放最大的数字 
        cin >> n;
        for ( i = 0; i < n; i++ ){
            cin >> x;
            MemTable[i] = x;
            ExitMem[x] ++;
            if ( x >= max_num ) max_num = x; 
        }   
        for ( i = 0; i < n; i++ ){
            cin >> x;
            GroupTable[x][MemTable[i]] ++;
            if ( NumTable[x] == 0 ) group_num ++;
            NumTable[x] ++;
            if ( x >= max_group ) max_group = x;
        }
        for ( i = 0; i <= max_group; i++ ){
            if( NumTable[i] != 0){
                cout << i << '=' << '{';
                for ( j = 0; j <= max_num; j++ ){
                    if ( ExitMem[j] != 0 ){
                        if ( j != max_num ){
                            cout << j << '=' << GroupTable[i][j] << ',';
                        }
                        else{
                            cout << j << '=' << GroupTable[i][j] ;
                        }
                    }       
                }
                cout << '}' <<endl;
            } 
        } 
        m --;
    }
    return 0;
}       

问题 C: Be Unique (20)
时间限制: 1 Sec 内存限制: 32 MB

题目描述
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.
样例输入
7 5 31 5 88 67 88 17
5 888 666 666 888 888
样例输出
31
None

解题思路
(1)用数组num[i] (i=1….n)记录按顺序输入的数据;
(2)用数组numTable[num[i]] (i=1….n)计数输入数据的个数;
(3)按照输入顺序读取numTable[num[i]] (i=1….n)中的数值,如果个数等于1则输出当前的num[i],若到循环结束,输出“None”。

Submission

#include<stdio.h>
int main(){
    int n, i, j;
    while ( scanf("%d", &n) != EOF ){
        int numTable[10001] = {0};
        int num[100001] = {0};
        int flag = 0;
        int max_x = 0;
        for ( i = 0; i < n; i++ ){
            scanf("%d", &num[i]);
            numTable[num[i]]++;
            if ( max_x < num[i] ) max_x = num[i]; 
        }
        for ( i = 0; i < n; i++ ){
            if ( numTable[num[i]] == 1 ){
                printf("%d\n", num[i]);
                flag = 1;
                break;
            }
        }
        if ( flag == 0 ){
            printf("None\n");
        }
    }
    return 0;
}    

问题 D: String Subtraction (20)
时间限制: 1 Sec 内存限制: 32 MB

题目描述
Given two strings S1 and S2, S = S1 - S2 is defined to be the remaining string after taking all the characters in S2 from S1. Your task is simply to calculate S1 - S2for any given strings. However, it might not be that simple to do it fast.
输入
Each input file contains one test case. Each case consists of two lines which gives S1 and S2, respectively. The string lengths of both strings are no more than 104. It is guaranteed that all the characters are visible ASCII codes and white space, and a new line character signals the end of a string.
输出
For each test case, print S1 - S2 in one line.
样例输入
They are students.
aeiou
样例输出
Thy r stdnts.

解题思路
(1)把待查询的s2的每个字母的ASCII码当成其数组下标
(2)思路与前面几题的数字查询一样

Submission

#include<stdio.h>
#include<string.h>
int main(){
    int n, i, j;
    char str1[10010] = {0};
    while ( gets(str1) ){
        char str2[10010] = {0};
        char str2Table[10010] = {0};
        gets(str2);
        for ( i = 0; i < strlen(str2); i++){
            str2Table[str2[i]]++;
        }
        for ( i = 0; i < strlen(str1); i++){
            if ( str2Table[str1[i]] == 0 ){
                printf("%c", str1[i]);
            }
            else continue;
        }
        printf("\n");
    }
    return 0;
}    

猜你喜欢

转载自blog.csdn.net/Marilynmontu/article/details/82051901