【Leetcode】287.Find the Duplicate Number 解题报告

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/dpengwang/article/details/88075486

在这里插入图片描述
找出数组中重复的数,题目中要提取出如下关键信息

  • 数组有n+1个数,每个数的范围是1-n(注意有n个数,每个数的范围是1-n的区别)
  • 重复的数可能有多个一个,但值都是相同的

方法1 map法 Time O(n) Space O(n)

class Solution1(object):
    def findDuplicate(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        dictionary = {}
        for num in nums:
            if num in dictionary:
                return num
            else:
                dictionary[num] = 1

方法2 排序法 Time O(nlogn) Space O(1)

class Solution2(object):
    def findDuplicate(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        nums.sort()
        for i in range(len(nums)):
            if nums[i] == nums[i+1]:
                return nums[i]

方法3 下标法 Time O(n) Space O(1)

因为数组中每个元素的取值范围为1-n,我们可以将访问过的元素,根据他的值,将对应位置的元素变为相反数,如果再次遇到负值,说明该元素重复。这种方法的缺点是原来的数组会被改变
eg: a[1] = 2 ,我们将a[2]变为 -a[2],a[3] =2是,我们再次访问a[2]发现其为负,说明之前2已经出现过了

class Solution3(object):
    def findDuplicate(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        for i in range(len(nums)):
            index = abs(nums[i])
            if nums[index-1] < 0:
                return index
            else:
                nums[index-1] *=-1

方法4 位操作法 Time O(32n) Space O(1)

我们按位遍历数组中的数和1-n,统计对应的bit上出现的次数,如果重复了某个数,那么该位置上肯定多了个1。
注:这种方法可行是因为题目条件:数组有n+1个数,每个数的范围是1-n,如果条件改为:有n个数,每个数的范围是1-n,那么此方法不适用

class Solution4(object):
    def findDuplicate(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        res = 0
        for i in range(32):
            bit  = 1 << i
            array_count = 0
            origin_count = 0
            for i in range(len(nums)):
                if nums[i] & bit >0:
                    array_count +=1
                if i>0 and i&bit >0:
                    origin_count +=1
            if array_count > origin_count:
                res += bit
        return res

方法5 快慢指针法 Time O(n) Space O(1)

数组中元素的值可以看做是其指向下一个元素的下标
eg:
13422可以看做为 1->3->2->4->2(即又指向了2形成了一个换),我们用快慢指针法找出环的入口即可

class Solution5(object):
    def findDuplicate(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        slow = nums[0]
        fast = nums[slow]
        while(slow != fast):
            slow = nums[slow]
            fast = nums[nums[fast]]

        fast = 0
        while(fast != slow):
            fast = nums[fast]
            slow = nums[slow]
        return fast

方法6 二分查找法 Time O(nlog(n)) Space O(1)

主要思想如下:
我们根据最大最小值确定一个中位数,然后遍历数组记录小于等于middle的数有多少个。
没有重复的情况下小于等于middle的数应该有middle,如果大于middle,说明重复的数出现在middle左侧,反之在右侧
查找log(n)次,每一次查找中要遍历一次数组O(n)

class Solution6(object):
    def findDuplicate(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        low = 1
        high = len(nums)-1
        while(low < high):
            middle = (low + high)//2
            count = 0
            for num in nums:
                if num <= middle:
                    count +=1
            if count <= middle:
                low = middle+1
            else:
                high = middle
        return low

猜你喜欢

转载自blog.csdn.net/dpengwang/article/details/88075486