携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第8天,点击查看活动详情 本题的任务很简单:将给定的无重复正整数序列插入一个散列表,输出每个输入的数字在表中的位置。所用的散列函数是 H(key)=key%TSize,其中 TSize 是散列表的表长。要求用平方探测法(只增不减,即H(Key)+i2)解决冲突。
注意散列表的表长最好是个素数。如果输入给定的表长不是素数,你必须将表长重新定义为大于给定表长的最小素数。
输入格式:
首先第一行给出两个正整数 MSize(≤104)和 N(≤MSize),分别对应输入的表长和输入数字的个数。随后第二行给出 N 个不重复的正整数,数字间以空格分隔。
输出格式:
在一行中按照输入的顺序给出每个数字在散列表中的位置(下标从 0 开始)。如果某个数字无法插入,就在其位置上输出 -
。输出间以 1 个空格分隔,行首尾不得有多余空格。
输入样例:
4 4
10 6 4 15
输出样例:
0 1 4 -
代码长度限制 16 KB
时间限制 400 ms
内存限制 64 MB
PS:学过离散数学的同学对这题目还是比较了解的,不了解没关系
所谓线性探测即为余数+i²(i从0~表长)
如果超过了表长就没有意义了
思路分析:
- 首先要做的是找一个比MSIZE大且最小的素数(如果MSIZE不是素数的话)
- 我用的是比较简单的试除法
- 由于是线性探测,我们之间使i从0开始加到MSIZE即可(按照离散数学的原理知道超过MSIZE就没有意义了)
- 模拟
代码如下:
#include<iostream>
#include<string>
using namespace std;
const int N = 1e4 + 5;
bool a[N];
//找素数
bool Prime(int x) {
if (x == 1 || x == 0)
return false;
for (int i = 2; i <= x / i; i++)
if (x % i == 0)
return false;
return true;
}
//插入
void func(int x,int MSIZE) {
//直接从0开始,直到表长(0即是直接找)
for (int i = 0; i < MSIZE; i++) {
if (!a[(x + i * i) % MSIZE]) {
a[(x + i * i) % MSIZE] = true;
cout << (x + i * i) % MSIZE;
return;
}
}
cout << '-';
}
int main()
{
int MSIZE, n;
cin >> MSIZE >> n;
while (!Prime(MSIZE))
MSIZE++;
for (int i = 0; i < n; i++) {
int x;
cin >> x;
if (i != 0)
cout << " ";
func(x, MSIZE);
}
}
结果如下:
PS:成功解题=理清思路+一定的技巧~