剑指offer秋招准备(python版)---面试题3 ---附加 二分查找

题目:在一个长度为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])

猜你喜欢

转载自blog.csdn.net/houyaqiong/article/details/80852533
今日推荐