剑指offer(3)——寻找数组中的重复数

一、题目描述:

在一个长度为n的数组里,所有的数字都在0~n-1范围内。数组内某些数字是重复的,但不知道有几个数字是重复的,也不知道每个数字重复了几次,请找出数组中任意一个重复的数字。例如,如果输入数组{2,3,1,0,2,5,3},那么对应的输出是重复的数字2或3

解题思路:
(1)思路一:排序。
最简单的思路就是将数组排序一下,然后排序完了从头遍历一遍,就可以知道重复的数字有哪些了,但是这样的时间复杂度是O(n*log n)。显然时间复杂度还是很高,那么有没有其他的方法可以更快一些呢?

(2)思路二:哈希表
第二种思路是我们可以从头到尾遍历一遍数组的时候,当遇到一个没有出现的数将其加入哈希表,这样我们每次做判断只需要O(1)的时间复杂度,再加上遍历一遍数组,总共的时间复杂度为O(n)。然而这样的方式虽然我们达到了时间复杂度被降低了,可是却浪费了一个大小为O(n)的哈希表为代价的。那么还有更好的方法还能再降低空间复杂度吗?

(3)思路三:充分利用数组的下标
注意题目说长度为n的数组中,所有的数字都是再0~n-1之间的,也就是说这里面每一个的数字都可以当作数组的下标使用(而不会越界),那么我们的思想就可以是将每个数字放在自己对应的下标的地方,当有个数字准备去自己的下标的地方的时候,如果发现那个地方以及有一个和他一模一样的数字待在那里,那么就断定这个数字重复了。这样我们的时间复杂度就是遍历一遍数组为O(n),空间复杂度也降低在了此数组中,为O(1)。

下面我们那题目的例子列出思维的步骤:
为了叙述方便,我们改造一下数组[2,0,1,2,3]:

  • 发现下标为0的位置的数不是0,而是2。做交换操作,把2送回下标为2的位置。(此时数组变成了[1,0,2,2,3])
  • 发现此时下标为0处的数字仍然不是0,那么又送1回下标为1的位置。(数组变为[0,1,2,2,3])
  • 此时current为0,发现此时0下标处的数字为0,current += 1
  • 此时current为1,发现此时1下标处的数字为1,current += 1
  • 此时current为2,发现此时2下标处的数字为2,current += 1
  • 此时current为3,发现此时3下标处的数字不是3,而是2,而把2送回下标为2的地方的时候发现那里以及有一个2了,于是返回2重复(此时跳出程序即可满足题目要求了)

二、代码实现:


def searchRepetitiveNumber(arrayOne):
    length = len(arrayOne)
    current = 0
    while current < length:
        if arrayOne[current] == current:
            current += 1
        elif arrayOne[current] != arrayOne[arrayOne[current]]:
        
        	#交换操作
            flag = arrayOne[current]
            x,y = arrayOne[current],arrayOne[arrayOne[current]]
            arrayOne[flag] = x
            arrayOne[current] = y

        else:
            print("%d is repetitive!" % arrayOne[current])
            current += 1
    print("over!")

if __name__ == '__main__':
    arrayOne = [9,8,7,6,5,7,6,5,4,0]
    if not isinstance(arrayOne,list):
        print("input wrong!")
    else:
        searchRepetitiveNumber(arrayOne)


注意:交换操作的代码不可以写成:

arrayOne[arrayOne[current]] , arrayOne[current] = arrayOne[current] , arrayOne[arrayOne[current]]

详情请看我的另一篇博客《你真的知道a,b = b,a是怎么实现的吗?(python交换逻辑)》.

I am very glateful that 你看到这里了哦~下回再见ヾ(o◕∀◕)ノヾ
Thx
在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值