leetcode 【287 Find the Duplicate Number】【Python】

本题同样让我们找数组中重复的数字,但是给出了很多限制条件。其实leetcode好像对一些限制条件,无法做出判断,我们还是自我严格要求的好哦!

首先,第一个不可以改变数组,其实这个就是限制了我们排序,如果排序,然后再遍历一下很快就能找到重复的数字了,时间复杂度O(nlogn),空间复杂度O(1);
其次,空间复杂度O(1),这个限制了我们使用hash查找,因为hash时间复杂度是O(1),但是空间要O(n);
其次,时间复杂度小于O(n^2),这个限制了我们暴力求解,循环两次也可以得到结果,但是时间复杂度需要O(n^2);
最后,它说数组里重复的数字可能重复不止两次,这个限制了我们使用数学方法,也就是如果只有一个数重复了两次,我们可以等差求和,然后相减就可以得到结果了。

然后,我们回头看这四种解法,明显是第三种存在可以优化的地方,n^2可以降低到nlogn,一般使用的就是二分法了。找到中间数mid,然后遍历数组,如果大于中间数的数的个数,那么说明重复的数字在前半段,我们类似递归的思想,再次在前半段执行,同样如果小于说明在后半段出现。这里注意我们是和mid比较而不是nums[mid],因为数字固定是在0~n之间的数字。时间复杂度还是O(nlogn),空间复杂度O(1)

class Solution(object):
    def findDuplicate(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        left = 0
        right = len(nums) - 1
        while(left <= right):
            mid = left + (right - left)/2
            count = 0
            for i in range(len(nums)):
                if nums[i] <= mid :
                    count += 1
            if count > mid :
                right = mid - 1
            else:
                left = mid + 1
        return left

看到leetcode的提示有two points,这个一直不明白,看到别人的博客,原贴地址,https://segmentfault.com/a/1190000003817671
这里讲到了相应的原理,如果我们的序列是没有重复的,例如,[1,2,3]。那么可以由每一个下标对应一个数字,0->1 1->2 2->3,我们把这种映射关系应用出来,从下标0开始,找到0对应的数字,然后将这个数字作为新的下标找到新的数字,直到超出下界。比如这个例子中我们的路径就是0->1->2->3。
那么如果序列是重复的,[1,3,3,2],那么就会有下标对应数字时会有重复,0->1 {1,2}->3 3->2,那么我们的路径就会出现环! 0->1->3->2->3->2…,会出现3 2 这个环,那么环开始的地方就是重复的数字啦。这时我们利用的是leetcode中Linked List Cycle || 的方法,具体可以参见那篇博客。

class Solution(object):
    def findDuplicate(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        slow = nums[0]
        fast = nums[nums[0]]
        while(slow != fast):
            slow = nums[slow]
            fast = nums[nums[fast]]
        fast = 0
        while(fast != slow):
            slow = nums[slow]
            fast = nums[fast]
        return slow
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值