牛客 剑指offer JZ3数组中重复的数字

题目传送门:JZ3 数组中重复的数字

解法一:排序法,先给数组排序,然后比较第i个元素和第i+1个元素是否相等,如果相等则说明有重复的数字。

        这种解法的时间复杂度是排序的时间复杂度,最小时间复杂度是O(nlogn),所有操作都在原数组上进行,只需要额外的排序指针,空间复杂度是O(1)。

解法二:哈希表法,利用哈希表可以在O(1)时间内快速查找的性质。从头到尾扫描数组,并把数组的数字添加到哈希表内,添加数字到哈希表前先查找数字是否在哈希表内,如果不在,则添加数字;如果在,则说明在此之前已经添加过这个数字进去,发现重复的数字了,并返回这个重复数字。

        这种解法的时间复杂度是O(n),也就是扫描数组的时间复杂度,查找哈希表的时间是O(1)不影响从到到尾扫描数组的时间复杂度,空间复杂度也是O(n),需要创建一个和数组同等规模的哈希表存储数组的元素进行查找。这种解法优于排序法,时间复杂度一般优先于空间复杂度。

解法三:重排数组法,这里的重排是说把数组重排成numbers[i]=i,也就是数组元素的值等于下标的值。回顾题目的条件,数组的数字都在【0,n-1】的范围内,解法一和解法二都没有利用这一条件,重排数组利用上这个条件可以实现时间复杂度O(n)和空间复杂度O(1)。

        如果数组中没有重复的数字,那么数字i将出现在数组的第i个位置上,如果有重复的数字,则一个位置上可能有多个元素,有的位置没有元素。

        关键是如何实现重排数组

        从头到尾扫描数组的每个元素,如果numbers[i]=i,那就跳过这个元素接着扫描下一个元素,如果numbers[i]!=i,就比较numbers[i]和numbers[numbers[i]],如果两数相等,说明有重复数,这个重复数就是numbers[i].如果不相等,就交换numbers[i]和numbers[numbers[i]]。然后继续进行这个下标i位置上的比较和交换,不停的比较numbers[i]和numbers[numbers[i]],直到numbers[i]=i或者numbers[i]=numbers[numbers[i]]

        这里应当有个隐藏的结论,我目前还没有理解这个结论,也是解法三的前提,即如果数组元素都不重复,使得数组数字等于下标,只需要不停的交换数组数字和以数组数字为下标的位置的数字,即进行swap(numbers[i],numbers[numbers[i]])的操作,就可以把i放到他应该的位置上。关键字,数组下标排序,之后补上结论的证明

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值