题目描述:
在一个长度为n+1的数组里的所有数字都在1~n的范围内,所以数组中至少有一个数字是重复的。请找出数组中任意一个重复的数字,但是不能修改输入的数组。
按照二分查找的思路,将1-n分成两半,假如将1-n分成1-m和m+1到n。如果1~m中的数字的数目超过m,那就说明有重复数字;否则,另一半中一定有重复的数字。我们可以继续把包含重复数字的区间继续二分,直到找到一个重复的数字。
class Solution:
def duplicate(self, numbers):
if numbers == []:
return False
length = len(numbers)
start = 1
end = length -1
while end >= start :
middle = int((end-start)/2) + start
count = self.countNum(numbers,length,start,middle)
if end == start:
if count >1 :
print True
return True
else:
break
if count > (middle - start) +1:
end = middle
else:
start = middle+1
return False
def countNum(self,numbers,length,start,end):
count = 0
for i in range(length):
print numbers[i]
if numbers[i] <1 or numbers[i] >length :
return False
if start<= numbers[i] <=end :
count+=1
return count
ss = Solution()
ss.duplicate([4,2,3,1,2,5])
这种方法虽然不需要辅助空间O(n),但是后面每半个区间都需要遍历整个数组,函数countNum将被调用O(logn)次,每次需要O(n)的时间,因此总的时间复杂度是O(nlogn),空间复杂度为O(l)。相当于用时间换空间了。
现在来总结下关于数组中重复数字的问题,利用辅助空间的话,时间和空间复杂度都是O(n);利用下标于数字对应关系的话时间复杂度是O(n),空间复杂度是O(l),但是需要改变数组;利用二分查找类似思路的方法,时间复杂度是O(nlogn),空间复杂度O(l),所以要问清楚面试官他想要空间效率高的呢?还是时间效率高的呢?能不能改变数组呢?一方面体现交流能力,一方面能最快的写出答案。