题目:在一个长度为n+1的数组中,元素的大小在1~n之间(都是整数),说明一定存在重复数字,试问能不能在不修改数组的情况下找到一个重复的数字。实例【2,3,5,4,3,2,6,7】共8个数,在1到7的范围内,取中间的数字4,1~4之间包括1/2/3/4,在数组中,在这个范围内的数为5个,超过了该范围应该有的个数,故重复数字出现在1~4区间,之后继续这个过程,直至范围内数字个数等于2.
二分查找理念:一定有一个数出现了两次,将数组的范围一分为二,如果说没有重复的数字情况下,每个范围内数字个数都应该等于该范围的大小,如果超过了该范围,即是重复的数字出现在该范围。原因:一定有重复数字,而且,如果范围内有缺失数字的话,重复数字还不止一个。
该算法的时间复杂度o(nlogn),空间O(1),拿时间换空间,还可以用空间换时间,比如之前采用的重排数组、字典法
可以根据面试官的要求(找到一个、所有)、或者性能要求(时间效率优先、空间效率优先)选取不同的算法
class Solution:
def findSameNum(self,A):
if len(A)<2:
return False
for i in range(len(A)):
if A[i]<1 or A[i]>=len(A):
return False
left=1
right=len(A)-1
while left<right:
mid=(right-left)//2+1#尽量分布均匀
leftFre=self.findFre(A,left,mid)
if leftFre>mid-left+1:
right=mid
else:
left=mid+1
print(left)
return left#总的时间复杂度nlogn,注意返回的是left,而非A
def findFre(self,A,left,right):#时间复杂度n
fre=0
for item in A:
if item>=left and item<=right:
fre+=1
return fre
example=Solution()
example.findSameNum([2,3,5,4,3,2,6,7])