一个有推理过程的算法题解博客
不同于其他博客,这个会努力把每一步推导过程写出来,从而易于理解和记忆
如果感觉有用,请在评论区留言
原题
In data structure Hash, hash function is used to convert a string(or any other type) into an integer smaller than hash size and bigger or equal to zero. The objective of designing a hash function is to “hash” the key as unreasonable as possible. A good hash function can avoid collision as less as possible. A widely used hash function algorithm is using a magic number 33, consider any string as a 33 based big integer like follow:
hashcode(“abc”)
= (asc(a)*33^2 + asc(b)*33 + asc(c)) % HASH_SIZE
= (97*33^2 + 98*33 + 99) % HASH_SIZEhere HASH_SIZE is the capacity of the hash table (you can assume a hash table is like an array with index 0 ~ HASH_SIZE-1).
Given a string as a key and the size of hash table, return the hash value of this key.
Example For key=”abcd” and size=100, return 78
Clarification For this problem, you are not necessary to design your own hash algorithm or consider any collision issue, you just need to implement the algorithm as described.
说明
1. 大小写不用特别处理,直接使用对应的ascii值即可
2. HASH_SIZE 和 33 没有关系
3. 中间结果需要设置为long long,因为HASH_SIZE可能很大,接近INT上限,那样会溢出
最朴素的解法
根据题意,直接将字符串转化为一个33进制的数,然后对hash_size取模。但是字符串稍微长一些,就会越界。
int hashCode(string key,int HASH_SIZE) {
if (key.empty()) return 0;
if (HASH_SIZE <= 0) return -1;
long long magic = 33, n = 1, hashcode = 0;
for (int i = key.size() - 1; i >= 0; i--) {
hashcode += (key[i] * n) % HASH_SIZE;
n *= magic;
}
return hashcode % HASH_SIZE;
}
已知最优解
通过整理数学公式,变成另外一种形式,从而避开大数运算
根据 (a + b)%M = (a%M + b%M)%M
hashcode(abc)
= (a*33^2 + b*33 + c)%M
= (33(33*a + b) + c)%M
= (33(33(33*0 + a) + b) + c)%M
= (33(33(33*0 + a)%M + b)%M + c)%M
核心过程
中间结果初值为0
将中间结果乘以33,加上当前最高位的字母(从a开始计算),然后再取模
不断循环直到处理完所有字母
int hashCode(string key, int HASH_SIZE) {
if (key.empty()) return -1;
if (HASH_SIZE <= 0) return -1;
long long hashSum = 0;
for (int i = 0; i < key.size(); i++) {
hashSum = (33 * hashSum + key[i]) % HASH_SIZE;
}
return hashSum;
}
另一种思路
也是数学公式整理
hashcode(abc)
= (a * 33^2 + b * 33 + c) % M
= (a * 33^2 % M + b * 33^1 %M + c *33^0 %M ) %M
这样就能够利用快速幂取模的算法,计算33^n%M的值,并且保证计算过程中不会出现很大的中间结果
这里从最低位c开始计算
int hashCode(string key,int HASH_SIZE) {
if (key.empty()) return 0;
if (HASH_SIZE <= 0) return -1;
long long magic = 33, n = 0, hashcode = 0;
for (int i = key.size() - 1; i >= 0; i--) {
hashcode += ((long long)key[i] * fastPower(magic, HASH_SIZE, n++));
hashcode %= HASH_SIZE;
}
return hashcode;
}
int fastPower(int a, int b, int n) {
if (b == 0 || n < 0) return -1;
if (n == 0) return 1 % b;
if (n == 1) return a % b;
int res = 1;
while (n) {
if (n & 1) res = (long long)res * a % b;
a = (long long)a * a % b;
n >>= 1;
}
return res;
}
一个有推理过程的算法题解博客
不同于其他博客,这个会努力把每一步推导过程写出来,从而易于理解和记忆
如果感觉有用,请在评论区留言