LeetCode每日一题 缺失正数 哈希表

题目
给你一个未排序的数组,让你找到最小的正整数
如题:在这里插入图片描述
我们当然可以依旧使用暴力算法界问题,但由于题目限定,时间复杂度为O(n),那么暴力算法肯定不能解决,我们可以先简单理一下暴力法的思路,即按照数组的长度,从1到 len(nums) 依次判断,每个数字都要遍历一遍数组确认是否存在,若存在,则返回,若不存在,则直接输出,时间复杂度应该为 O (n2)。

今天我们主要提一下哈希表,用哈希表的算法解一下这道题:

我们先了解一下什么是哈希表:

哈希表

哈希表的基础依旧是数列,但不一样的是有key-value作为指标和索引,和数组相似,在一个数组中,对应的下标可以表示该数组中对应的数列,例如,在[0,2,4,6,8] 中,nums[ 2 ] 就可以代表在这个数组中的 4 这个数字,哈希表也是同理,在某一个关键字 key 中,有一个值 value 与之对应,我们可以通过遍历的方式,利用某个函数模型(哈希函数)将值一一对应到 entry 里面。

那为什么说这个函数优秀呢?

一个很形象的例子,在我们通讯录中,找寻一个人一般不会一个一个找,而是通过首字母来快速定位这个人名字出现的大致范围,而这就是哈希表在算法上的优越性,关于如何使用map,可以点击此处了解,而关于哈希表的通俗讲解,可以在此处看一篇小白相对好理解的博文

解题

然后我们来试图解解一下这个题,同样的问题出现了,不符合这个题目的限定条件,如果我们将每个数组都放入哈希表中,利用key值来快速定位,虽然在时间上可以达到目标,但是在储存上,将和数组的长度一样,为 O( n ) ,所以,我们可以采用官方的解法,将哈希表的方式变动一下,来得出较好的结果。

首先,我们先分析一下这道题,和暴力解法一致的是,缺失的数字一定在 1 到 len(nums) 中产出,若出现负数,则占有了正数的位置,如果是出现了大于长度的数字,则较小的数字就被空下了。

那怎么样用哈希表的思想来解决题目呢,就是像哈希表一样,先行遍历一次数组,然后在下标做一个标记,然后第二次遍历是,只需要找寻这个下标就可以,具体思路如下:

首先解决的是负数的问题,先把所有负数变为1,当然,如果这样的话,就要先查看数组中是否存在 1,若不尊在,则直接返回。

然后,遍历数组,将数组中每一个数字作为下标,找寻到这个位置的数字,将其变为负数,即相当于这个数字被使用过,所以对应的位置打好标记,这样说可能有点难理解,我们用一个例子来解释:

[2, 1 ,4, 6] 在这个数组中,在nums[ 0 ]处的数字为2,则nums[ 2 ] 处的数字变为 -4,再次遍历的时候,这个地方的数字为负数,则下标被放弃,直接跳过,没有被标记的数字,即正数的地方的下标,就是缺失的那个正整数。

具体代码如下:

func firstMissingPositive(nums []int) int {
    n := len(nums)
   found := 0
   //先检查是否有1,若有1,或长度过短,可以直接返回答案
	for i := 0; i < l; i++ { 
		if nums[i] == 1 {
			found+=1
			break
		}
	}
	if found == 0 { 
		return 1
	}
	if n == 1 { 
		return 2
	}
	//变为正数做好标记
    for i := 0; i < n; i++ {
        num := Abs(nums[i])
        if num <= n {
            nums[num - 1] = -Abs(nums[num - 1])
        }
    }
    //搜索
    for i := 0; i < n; i++ {
        if nums[i] > 0 {
            return i + 1
        }
    }
    return n + 1
}

func Abs(x int) int {
    if x < 0 {
        return -x
    }
    return x
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值