Quadratic probing 平方探查法
中文名为平方探查法。用于解决hash的collision。有算法笔记书的打开讲hash那一节的,曾经提到过。(忘了的活该卡一下午呜呜呜)
现在想想还是好气,以为那个词不重要(主要是看不懂)愣是卡了2小时……
当我们发现key的位置已经被占,可以通过一系列计算再确定其可以insert的下标
它的计算公式为 (key+a^2)%size, (key-a^2)%size (a=1,2,3,4……)(0< a <size)
当经过一个size的循环后,我们仍未找到可以插入的位置,则说明没有位置可插。
下面给出我的accept代码
#include<stdio.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int Max = 20010;
bool HashMapPrimeNumber[Max];
bool HashMap[Max];
void PrimeNumber() {
fill(HashMapPrimeNumber , HashMapPrimeNumber + Max, true);
HashMapPrimeNumber[0] = false;
HashMapPrimeNumber[1] = false;
for (int i = 2; i < Max; i++) {
if(HashMapPrimeNumber[i])
for (int j = i * 2; j < Max; j += i) {
HashMapPrimeNumber[j] = false;
}
}
for (int i = 0; i < Max; i++) {
if (HashMapPrimeNumber[i])
cout << i << " ";
}
}
int main() {
PrimeNumber();
int Size, Number;
cin >> Size >> Number;
while (HashMapPrimeNumber[Size] == false)
Size++;
for (int i = 0; i < Number; i++) {
int j;
int temp = 0;
cin >> temp;
for (j = 0; j < Size; j++) {
int key = temp + j * j;
key %= Size;
if (HashMap[key] == false) {
HashMap[key] = true;
cout << key << (i < Number - 1 ? " " : "\n");
break;
}
}
if (j == Size)
cout << "-"<< (i < Number - 1 ? " " : "\n");
}
return 0;
}
主要思路
- 打出素数表。记得不要写错循环条件,会导致无法accept……(可能又只有我一个人踩坑?顺带一提,假如写错,大概率会出现3 4点无法通过,卡3 4点的朋友记得检查素数表或者素数函数)
- 寻找一个刚好比user给出大的最小素数。
- 利用平方探查法,确定hash有效坐标。从0开始循环可以稍稍简化代码,从1开始也是一样的。
- key记得取模。
心得
- 多积累专业词汇。看到一些奇怪的,高效的算法,可以记一记名字,再试图理解算法。一是可以缓解不认识词的尴尬场面,二是可以积累优秀算法的写法。
- 有时候可以多怀疑一下自己认为必对的代码块,说不定就是因为你打错了个参数导致过不了呢?
- 平方探查法是一个可以解决hash collision的算法。还有一个叫拉链法。关于hash的算法还有很多,更高效的需要借助stl来实现。