自用笔记40——使用简单的哈希表

给定一个包含 0, 1, 2, …, n 中 n 个数的序列,找出 0 … n 中没有出现在序列中的那个数。

示例 1:

输入: [3,0,1]
输出: 2
示例 2:

输入: [9,6,4,2,3,5,7,0,1]
输出: 8

说明:
你的算法应具有线性时间复杂度。你能否仅使用额外常数空间来实现?

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/missing-number
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

int missingNumber(int* nums, int numsSize){
    int sum=0,sumt=0,i=0;
    sumt=(1+numsSize)*numsSize/2;
    for(i=0;i<numsSize;i++)
    {
        sum=sum+nums[i];
    }
    return sumt-sum;
}

啊这似乎有点似曾相识啊,这不是异或大兄dei吗。这次在做这道题时我能想到异或了,笔记没白做。

而且这次我能想到哈希表法,虽然还不是很清楚其概念。

哈希表是一种根据关键码去寻找值的数据映射结构,该结构通过把关键码映射的位置去寻找存放值的地方。
通过哈希表查找元素就好比是查字典,如果我想要获取“按”字详细信息,我肯定会去根据拼音an去查找 拼音索引(当然也可以是偏旁索引),我们首先去查an在字典的位置,查了一下得到“安”,结果如下。这过程就是键码映射,在公式里面,就是通过key去查找f(key)。其中,按就是关键字(key),f()就是字典索引,也就是哈希函数,查到的页码4就是哈希值。
在这里插入图片描述
哈希冲突/哈希碰撞就类似于查字典时相同的拼音会映射到同一个页码,又相当于非单调函数,即x1≠x2,但有f(x1)=f(x2)。
哈希冲突是无可避免的,如果要避免,就只能每个字典去新开一个页,然后每个字在索引里面都有对应的页码,这就可以避免冲突。但是会导致空间增大(每个字都要占用一页的空间)。
  只能尽量减少冲突带来的损失,而一个好的哈希函数需要有以下特点:
  1.尽量使关键字对应的记录均匀分配在哈希表里面(比如说某厂商卖30栋房子,均匀划分ABC3个区域,如果你划分A区域1个房子,B区域1个房子,C区域28个房子,有人来查找C区域的某个房子最坏的情况就是要找28次)。
  2.关键字极小的变化可以引起哈希值极大的变化。

这道题用简单的哈希表可以这样,以nums数组里的元素为索引创建一个全为1的哈希表(可以一开始将里面的元素全部初始化为0,然后将相应的元素位置赋值为1),然后从0~numsize去检查是否有某一项不为1,则返回那一项。当缺失的值为n时,需要另外加判断条件(因为一般循环从0到numsize-1)

int missingNumber(int* nums, int numsSize){
    int *hash = (int*)malloc(sizeof(int)*(numsSize + 2));
    memset(hash,sizeof(int)*(numsSize+2),0);
    for(int i = 0; i < numsSize; i++){
        hash[nums[i]] = 1;
    }
    for(int j = 0; j < numsSize; j++){
        if(hash[j] != 1)    return j;
        if(hash[numsSize]!=1)   return numsSize;  //处理边界问题
    }
    return -1; //没有查到的情况,return -1
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值