今天是基础数据结构的最后一个。至此我们的基础数据结构系列就结束了!!!
这几天先告一段落,等期末考试完继续更新算法系列。
哈希表又叫散列表,通常用数组来实现,又叫做哈希数组。
一、概念
常用哈希函数
1、直接定址法;
关键字本身就是哈希值,例如f(x) = x
;
2、平方取中法
3、折叠法
4、除留取余法(常用)
f(x) = x % m
5、位与法
哈希冲突解决方法
1、开放定址法
如果发生冲突则寻找下一个空地址。
2、链地址法
发生冲突后不换地址,使用链表将链接到当前的值的后面
第一题 41. 缺失的第一个正数
int hash[500002]; //定义哈希数组
int firstMissingPositive(int* nums, int numsSize) {
memset(hash, 0, sizeof(hash)); //初始化为0
// 遍历数组,传入哈希
for(int i = 0; i < numsSize; ++i) {
int v = nums[i];
//如果值负数或大于500000,那后面就不用看了,因为数组长度只有500000,里面必定有空值。
if(nums[i] <= 0 || nums[i] > 500000) {
continue;
}
hash[ v ] = 1;
}
for(int i = 1; ; ++i) {
if(!hash[i]) {
return i;
}
}
return -1;
}
第二题 387. 字符串中的第一个唯一字符
int firstUniqChar(char* s) {
int hash[26];
memset(hash, 0, sizeof(hash));
//遍历数组的方法;如果出现一次字符则+1
for(int i = 0; s[i]; ++i) {
hash[s[i] - 'a']++;
}
// 遍历数组判断当前对应的哈希表是否为1,返回索引值即可
for(int i = 0; s[i]; ++i) {
if(hash[s[i] - 'a'] == 1) {
return i;
}
}
return -1;
}
第三题 215. 数组中的第K个最大元素
#define BASE 10000
int hash[2 * BASE + 5];
int findKthLargest(int* nums, int numsSize, int k) {
memset(hash, 0, sizeof(hash));
for(int i = 0; i < numsSize; ++i) {
int index = nums[i] + BASE;
hash[index]++;
}
for(int i = 2 * BASE; i >= 0; --i) {
while( hash[i] ) {
k--;
hash[i]--;
if( k == 0 ) {
return i - BASE;
}
}
}
return -1;
}
第四题 1. 两数之和
hash[i]
代表数字i + hash[i] == target
;
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
//实现哈希表
#define BIT 16 //定义16位,我也不知道什么意思
#define MASK ((1 << BIT) - 1) //说是掩码,就是2^16 - 1 = 65535
#define MAGIC 1000000001 //定义一个边界,用于初始化哈希表
int hash[MASK + 1]; //创建哈希表
//初始化哈希表
void HashInit() {
//里面的值都赋值为取不到的值,表示为空
for(int i = 0; i <= MASK; ++i) {
hash[i] = MAGIC;
}
}
int HashFindAndInsert( int x ) {
int v = x & MASK; //于操作,等于将x变为正数,如果不是负数则就是x
while(1) {
//如果当前哈希数组为空则插入
if(hash[v] == MAGIC) {
hash[v] = x;
return v;
}else if(hash[v] == x) { //如果是x表明已经插入了,直接返回
return v;
}
v = (v + 1) * MASK; //如果不满足要求,v往前移动一位,直到满足要求
}
}
int pos[MASK + 1];
int* twoSum(int* nums, int numsSize, int target, int* returnSize) {
int *ret = (int *)malloc(sizeof(int) * 2);
*returnSize = 2;
HashInit();
memset(pos, -1, sizeof(pos));
for(int i = 0; i < numsSize; ++i) {
int idx = HashFindAndInsert(target - nums[i]); //得到target - b = a里面的a
if(pos[idx] != -1) {
ret[0] = pos[idx];
ret[1] = i;
return ret;
}
//
pos[ HashFindAndInsert(nums[i]) ] = i;
}
*returnSize = 0;
return ret;
}