听我的!想上岸北美科技公司先掌握这道题

该博客介绍了一种解决寻找数组中唯一重复数字的算法,使用了基于值的二分法。通过绘制折线图来分析,当折线超过y=x这条线时,表明遇到了重复的数。算法的时间复杂度为O(nlogn),并满足不修改数组、仅使用O(1)额外空间的要求。

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

彭博面试题:寻找重复的数

描述
给出一个数组 nums 包含 n + 1 个整数,每个整数是从 1 到 n (包括边界),保证至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。
1.不能修改数组(假设数组只能读)
2.只能用额外的O(1)的空间
3.时间复杂度小于O(n^2)
4.数组中只有一个重复的数,但可能重复超过一次

在线评测地址

样例1

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

样例 2:

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

解题思路
基于值的二分法。 这个题比较好的理解方法是画一个坐标轴:

  • x轴是 0, 1, 2, … n。
  • y轴是对应的 <=x 的数的个数,比如 <=0 的数的个数是0,就在(0,0)这个坐标画一个点。<=n 的数的个数是 n+1 个,就在 (n,n+1)画一个点。
    把所有的点连接起来之后,是一个类似下图的折线:

我们可以知道这个折线图的有如下的一些属性:

  1. 大部分时候,我们会沿着斜率为 1 的那条虚线前进
  2. 如果出现了一些空缺的数,就会有横向的折线
  3. 一旦出现了重复的数,就会出现一段斜率超过 1 的折线
  4. 斜率超过 1 的折线只会出现一次
    试想一下,对比 y=x 这条虚线,当折线冒过了这条虚线出现在这条虚线的上方的时候,一定是遇到了一个重复的数。 一旦越过了这条虚线以后,就再也不会掉到虚线的下方或者和虚线重叠。 因为折线最终会停在 (n,n+1) 这个位置,如果要从 y=x 这条虚线或者这条虚线的下方到达 (n,n+1) 这个位置, 一定需要一个斜率 > 1的折线段,而这个与题目所说的重复的数只有一个就是矛盾的。因此可以证明,斜率超过1 的折线只会出现1次, 且会将折线整体带上 y=x 这条虚线的上方。因此第一个在 y=x 上方的 x 点,就是我们要找的重复的数。
    时间复杂度是 O(nlogn)
    源代码
class Solution:
    """
    @param nums: an array containing n + 1 integers which is between 1 and n
    @return: the duplicate one
    """
    def findDuplicate(self, nums):
        start, end = 1, len(nums) - 1
        
        while start + 1 < end:
            mid = (start + end) // 2
            if self.smaller_than_or_equal_to(nums, mid) > mid:
                end = mid
            else:
                start = mid
                
        if self.smaller_than_or_equal_to(nums, start) > start:
            return start
            
        return end
        
    def smaller_than_or_equal_to(self, nums, val):
        count = 0
        for num in nums:
            if num <= val:
                count += 1
        return count

更多题解参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值