• LeetCode 287. 寻找重复数 | Python


    287. 寻找重复数


    题目来源:力扣(LeetCode)https://leetcode-cn.com/problems/find-the-duplicate-number

    题目


    给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。

    示例 1:

    输入: [1,3,4,2,2]
    输出: 2
    

    示例 2:

    输入: [3,1,3,4,2]
    输出: 3
    

    说明:

    • 不能更改原数组(假设数组是只读的)。
    • 只能使用额外的 O(1) 的空间。
    • 时间复杂度小于 O(n2) 。
    • 数组中只有一个重复的数字,但它可能不止重复出现一次。

    解题思路


    思路:二分查找

    这里需要注意,题意中说明,有 4 个提示。这里会限制一些方法,例如:

    • 对数组排序,重复数相邻,根据这个就可以找到重复数(这里违背【不能更改原数组】)
    • 使用哈希表,(这里违背【只能使用额外的 O(1) 算法】)
    • ...

    上面的方法,在没有限制的情况下,可以使用,但是在这里,由于题目给出了限制,所以暂不考虑。

    先看本题,【给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n)】,这是题目中给定的前提。

    根据这个前提,这里二分法的思路是先定一个数值(这里同样定 [left, right] 的中间值 mid),不过这里要统计的是原始数组中,小于等于这个 mid 的值的元素个数(这里定义为 count)。如果这个 count 严格大于 mid 的值的话,这个重复元素就会落在区间 [left, mid] 中。

    这里涉及一个原理:抽屉原理。关于 抽屉原理,大致是这样的一个现象:如果桌上有十个苹果,要把这十个苹果放到九个抽屉里,无论怎样放,我们会发现至少会有一个抽屉里面放不少于两个苹果。

    以题目中所给的示例 1 进行展开分析:

    [1,3,4,2,2]
    

    首先,我们知道,这里的数值 2 是重复值。现在,我们按照上面的思路来分析一下。

    这里有 5 个数字,即是 n + 1 = 5,n = 4,那么这里数组的数值都在 1 到 4 之间。

    现在先定一个值(根据上面所述的中间值 mid),这里定为 2,遍历数组,统计小于等于 2 的数字个数。这里可以看到,有 3 个值,严格大于 mid,所以重复值落在 [1, 2] 这个区间中。

    具体的代码实现如下。

    代码实现


    class Solution:
        def findDuplicate(self, nums: List[int]) -> int:
            size = len(nums)
    
            left = 1
            right = size - 1
    
            while left < right:
                # 先找中间值
                mid = left + (right - left) // 2
                # mid = (left + right) // 2
                # 遍历数组
                # 统计数组中小于等于中间值的元素个数
                count = 0
                for num in nums:
                    if num <= mid:
                        count += 1
                
                # 如果统计数严格大于中间值时,那么重复值将落在 [left, mid] 这个区间
                if count > mid:
                    # 将右边界缩小到 mid
                    right = mid
                # 否则重复值落在 [mid + 1, right]
                else:
                    left = mid + 1
            return left
    

    实现结果


    实现结果

    总结


    • 根据题意给定的前提,使用二分查找的思路,先找一个中间值 mid(在区间 [left, right] 中找)。
    • 统计原数组中小于等于中间值 mid 的个数 count,当 count 严格大于 mid 时,那么这个重复数值会落在 [left, mid] 区间中

    欢迎关注微信公众号《书所集录》

  • 相关阅读:
    mysql总结1
    shell 获取结果中的第n列,第n行
    automake中Makefile.am和configure.ac的格式及编译过程
    安卓常见错误解决方案
    kotlin 委托
    Kotlin 对象表达式和对象声明
    Kotlin 枚举类
    angular js自定义service的简单示例
    用angular.element实现jquery的一些功能的简单示例
    js判断中出现两个!!是什么意思?
  • 原文地址:https://www.cnblogs.com/yiluolion/p/12968529.html
Copyright © 2020-2023  润新知