算法學習——哈希

散列(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;
}    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章