数组中重复的数字 抽屉原理思想和一个小坑

很久没有更新了,惭愧…第一是虽然在家办公,杂活比较多,没啥心情写,第二且最重要的应该是懒癌患了…

打开LeetCode,惊叹,竟然出了剑指offer程序员面试金典的题库了,据说是不错的、很有针对性的书籍。现在能通过线上的优势来刷书了,开心…

话不多说,先来一题压压惊:数组中重复的数字

在这里插入图片描述
题没啥难的,有很多种方法可以解决。我这里只是参考了网上大神们的题解,即利用 桶排序+抽屉原理的思想,记录学习,并填掉一个Python赋值的坑。类似的思想还可以解决掉缺失的第一个正数

桶排序和抽屉原理具体是什么,网上搜一下,消化一下就行啦。这里不再多说。简单说说算法的思想:设整个数组是一个抽屉柜,而每个数字都应有属于它正确的位置,也就是抽屉。但如题目所说,存在重复的数字,那么我们在翻阅抽屉并存放东西的过程中,肯定会存在某个抽屉存在数字了,那么不难得到此时待放的数字为重复的数字。由题意,我们可以设每个数字代表着其所属的抽屉索引。

nums[i]而言,其值表示它所属的那个抽屉索引,那么我们将其放到正确的位置上。可以通过交换来处理,即

swap(nums[i], nums[nums[i]])

可以看到交换一次,就有当前拿在手里的数字放到了它该去的位置,直到发现某个抽屉已经存在数字了,就返回手里的数字。

if nums[i] == nums[nums[i]]:
	return nums[i]

很清晰,代码如下:

def findRepeatNumber(nums):
	n = len(nums)
	if n <= 1:
		# 其实也可以不用考虑
		return -1
	for i in range(n):
		while nums[i] != i:
			if nums[i] == nums[nums[i]]:
	        	return nums[i]
	        #这样写会出错 nums[i], nums[nums[i]] = nums[nums[i]], nums[i]
	    	nums[nums[i]], nums[i] = nums[i], nums[nums[i]]

好了,上面会出错的原因直接解释一下。

对于nums[i], nums[nums[i]] = nums[nums[i]], nums[i],举个栗子就清楚了,比如nums = [4,1,3,1,3], i = 0。虽然存在python并行赋值,但也要考虑顺序,即左边的先执行。首先nums[0]已经被赋值为nums[nums[0]],也就是说左边的赋值已经保证了nums[0] = 3,所以在执行右边赋值的时候,左边被赋值元素已经变为nums[nums[0]] => nums[3]了,而右边依然是之前的nums[0] = 4,因此最后的结果就是
[3,1,3,4,3],而非我们想要的[3,1,3,1,4],解决的方法就很简单了,就是不要去动待改变的数字就行。

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Key Board

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值