题目描述
在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
输入示例:[2,1,3,1,4]
输出示例:"true,1"
可复习的知识点:各大排序算法、哈希表
思路1:先进行排序,然后顺序查找到第一个重复的数字。用冒泡排序时间复杂度O(n^2),该代码中冒泡排序可添加flag进行优化,可替换成其他排序算法。
class Solution:
# 这里要特别注意~找到任意重复的一个值并赋值到duplication[0]
# 函数返回True/False
def duplicate(self, numbers, duplication):
# 这里用的是冒泡排序
index=len(numbers)
while index>1:
for i in range(index-1):
if numbers[i]>numbers[i+1]:
numbers[i],numbers[i+1]=numbers[i+1],numbers[i]
index=index-1
for j in range(len(numbers)-1):
if numbers[j]==numbers[j+1]:
duplication[0]=numbers[j]
return True
return False
冒泡排序的核心思想是每次比较处于相邻位置的两个数:
总共要排序n-1趟,第i趟的比较次数为n-i次。注意:如果某一趟排序中没有发生交换,那么冒泡排序就可以停止了,因此上面可以加一个flag优化一下。
思路2:对题目进行分析,因为长度为n的1维数组内,数组的范围是0~n-1。如果我们从让每个数字呆在相同索引值的位置这一想法出发,即让数字1呆在array[1],数字2呆在array[2]......从数组的最左端开始,判断索引i处的数字m是否等于i,如果相等则看下一个数字,如果不相等,则把数字m跟它作为索引查找到的值n进行交换。若m和n的值相等,那么,重复的数就找到了。注意了,一个是索引i和i处的值m是否相等,一个是m跟m作为索引找到的值n是否相等。每个数字最多被交换2次就能到自己的位置上去,所以时间复杂度为O(n):假设i处的数字m此时需要和m处的数字n进行一次交换,则数字m直接到达索引m处。数字n被换到索引i处。若n==i,那么数字n就不用再交换了,这就是它的归宿。如果不是,数字n只要和索引n处的数进行交换就到达了它的位置。所以最多交换的次数就是n这样的。(一顿暴风打字输出)
两种情况,以n=5,数字范围在0~4之间分别举个例子进行分析,再归纳一下:
1.数组内有重复的数,数组内顺序未知:[2,4,3,2,3,1]也可能是[2,3,2,1,1,1]
2.数组内没有重复的数,数组内顺序未知:[2,0,3,1,4],如果数组内没有重复的数,那么肯定会从[0,n-1]都有!
Python题解:
python的引用可把人坑惨了!!!!在写交换的时候千万注意,类似这样或者只用一个临时变量是错误的是非常不可取的(numbers[i],numbers[numbers[i]]=numbers[numbers[i]],numbers[i]),python的变量是引用变量,当numbers[i]重新赋值后,numbers[numbers[i]]中里面的那个会因为刚刚的重新赋值而发生改变!!!
# -*- coding:utf-8 -*-
class Solution:
# 这里要特别注意~找到任意重复的一个值并赋值到duplication[0]
# 函数返回True/False
def duplicate(self, numbers, duplication):
i=0
while i <len(numbers)-1:
if i==numbers[i]:
i=i+1
else:
if numbers[i]==numbers[numbers[i]]:
duplication[0]=numbers[i]
return True
tmp=numbers[i]
tmp2=numbers[numbers[i]]
numbers[i]=tmp2
numbers[tmp]=tmp
return False