LeetCode287-寻找重复数

本文探讨了在不改变原数组且仅使用O(1)额外空间的条件下,如何找到数组中唯一重复的整数。通过对比排序法与二分查找法,详细解析了两种方法的实现过程及效率分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

阿里的一面没过

天呐,我是不是太菜了

还是不能偷懒

坚持刷题吧!


题目描述:

给定一个包含 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) 。
数组中只有一个重复的数字,但它可能不止重复出现一次。

思路解析:

这一题看上去是有点像第229题求众数,因为题目已经告诉你了,在nums数组中一定存在一个重复数。当时有想到用摩尔投票法的思想来解题,可是又想到摩尔投票法是要求数字出现的次数超过1/n的,这里面n没有给定,所以还真不好用摩尔投票法来解决。

后来又想到一个很直接的方法,就是首先将数组nums排序,然后我们再从左至右依次遍历,只要是数字连续出现,那么该数字就是我们要找的众数。代码如下:

class Solution(object):
    def findDuplicate(self, nums):
        """
        排序法,查重
        :type nums: List[int]
        :rtype: int
        """
        nums.sort()
        for index in range(len(nums)-1):
            if nums[index] == nums[index+1]:
                return nums[index]


if __name__ == "__main__":
    nums = [3, 1, 3, 4, 2]
    duplicate_num = Solution().findDuplicate(nums)
    print(duplicate_num)

思路非常简单,真论执行效率也不差,达到了70%。但是呢,我们用了nums.sort()排序法,看似没有扩充空间,但还是临时分配了O(n)的空间,所以不符合题目的要求。那这也不能用,还有什么方法呢?在这儿得着重介绍一个概念:抽屉原理。概念如下:

桌上有十个苹果,要把这十个苹果放到九个抽屉里,无论怎样放,我们会发现至少会有一个抽屉里面放不少于两个苹果。

有了这个作为铺垫,我们可以用到了二分法来解决了。即定义一个中位数,值为选定nums集合内最大值和最小值的平均值。如果:小于等于 4 的个数如果严格大于 4 个,此时重复元素一定出现在 [1, 4] 区间里。凭此概念,代码如下:

class Solution(object):
    def findDuplicate(self, nums):
        """
        不同理解的二分法来解题
        :type nums: List[int]
        :rtype: int
        """
        left, right = 1, len(nums)-1
        while left < right:
            mid = (left + right) // 2
            cnt = 0
            for num in nums:
                if num <= mid:
                    cnt += 1
            # 根据抽屉原理,小于等于 4 的数的个数如果严格大于 4 个,
            # 此时重复元素一定出现在 [1, 4] 区间里

            if cnt > mid:
                # 重复的元素一定出现在 [left, mid] 区间里
                right = mid
            else:
                # if 分析正确了以后,else 搜索的区间就是 if 的反面
                # [mid + 1, right]
                left = mid + 1
        return left


if __name__ == "__main__":
    nums = [3, 1, 3, 4, 2]
    duplicate_num = Solution().findDuplicate(nums)
    print(duplicate_num)

执行效率还可以吧,在70%左右。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学习的学习者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值