1. 程式人生 > >PAT 1078 Hashing[一般][二次探查法]

PAT 1078 Hashing[一般][二次探查法]

alt rem http input bre span tput eml ram

1078 Hashing (25 分)

The task of this problem is simple: insert a sequence of distinct positive integers into a hash table, and output the positions of the input numbers. The hash function is defined to be H(key)=key%TSize where TSize is the maximum size of the hash table. Quadratic probing (with positive increments only) is used to solve the collisions.

Note that the table size is better to be prime. If the maximum size given by the user is not prime, you must re-define the table size to be the smallest prime number which is larger than the size given by the user.

Input Specification:

Each input file contains one test case. For each case, the first line contains two positive numbers: MSize (10?4??) and N (MSize) which are the user-defined table size and the number of input numbers, respectively. Then Ndistinct positive integers are given in the next line. All the numbers in a line are separated by a space.

Output Specification:

For each test case, print the corresponding positions (index starts from 0) of the input numbers in one line. All the numbers in a line are separated by a space, and there must be no extra space at the end of the line. In case it is impossible to insert the number, print "-" instead.

Sample Input:

4 4
10 6 4 15

Sample Output:

0 1 4 -

題目大意:向一個Hash表中插入不同的數字,並且給出了一個 TSize ,就是哈希的函數,用輸入的數字%TSize,如果TSize不是素數,那麽就轉化為最近的大於它的素數。

按輸入順序輸出每一個數的位置,從0開始,如果一個數不能插入(也就是存在沖突問題)那麽就輸出-。

技術分享圖片
#include <iostream>
#include <cmath>
#include<vector>
#include <map>
using namespace std;

bool isPrime(int m){
    int x=sqrt(m)+1;
    for(int i=2;i<x;i++){
        if(m%i==0)return false;
    }
    return true;
}
int getPrime(int m){
    for(int i=m+1;;i++){
        if(isPrime(i))return i;
    }
}
int main() {
    int m,n;
    cin>>m>>n;
    if(m!=1&&!isPrime(m)){
        m=getPrime(m);
    }
    if(m==1)m=2;
    vector<int> vt(n);
    for(int i=0;i<n;i++){
        cin>>vt[i];
    }
    map<int,int> mp;
    for(int i=0;i<n;i++){//遍歷一個,打印一個就可以解決這個順序問題。
        int x=vt[i]%m;
        if(mp[x]==0){
            cout<<x;
            mp[x]=1;
        }else
            cout<<"-";
        if(i!=n-1)cout<<" ";
    }

    return 0;
}
View Code

//第一次在牛客網上提交錯誤,是因為出現了測試:

1 1

1

這是1不是素數,應該把1轉化為2才對。在pat上提交,最後一個測試點答案錯誤。牛客網上的通過率只有10%。。。應該是因為我沒有用直接將大數內素數求出來的方法。

看了題解,才知道原來是需要使用二次探查法:

轉自:https://www.liuchuo.net/archives/2297

1.如果當前key%value沒被占用,那麽就放下;

2.如果key%value被占用了,那麽就設置一個step從1到value-1,判斷(key+step*step)%value是否被占用了,如果未被占用那麽就放下;如果都被占用了那麽就真的無法放下了。

我的AC:

#include <iostream>
#include <cmath>
#include<vector>
#include <map>
using namespace std;

bool isPrime(int m){
    int x=sqrt(m)+1;
    for(int i=2;i<x;i++){
        if(m%i==0)return false;
    }
    return true;
}
int getPrime(int m){
    for(int i=m+1;;i++){
        if(isPrime(i))return i;
    }
}
int main() {
    int m,n;
    cin>>m>>n;
    if(m!=1&&!isPrime(m)){
        m=getPrime(m);
    }
    if(m==1)m=2;
    vector<int> vt(n);
    for(int i=0;i<n;i++){
        cin>>vt[i];
    }
    map<int,int> mp;
    for(int i=0;i<n;i++){//遍歷一個,打印一個就可以解決這個順序問題。
        int x=vt[i]%m;
        if(mp[x]==0){
            cout<<x;
            mp[x]=1;
        }else{
            int step=1;
            bool flag=false;
            for(int j=step;j<m;j++){
                int y=(vt[i]+j*j)%m;
                if(mp[y]==0){
                    cout<<y;
                    mp[y]=1;
                    flag=true;break;
                }
            }
            if(!flag)cout<<"-";
        }

        if(i!=n-1)cout<<" ";
    }

    return 0;
}

//學習了二次探查法。

PAT 1078 Hashing[一般][二次探查法]