再从萌新开始-Leetcode每日题解-287. Find the Duplicate Number

287Find the Duplicate Number(Medium

Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), prove that at least one duplicate number must exist. Assume that there is only one duplicate number, find the duplicate one.

Note:

  1. You must not modify the array (assume the array is read only).
  2. You must use only constant, O(1) extra space.
  3. Your runtime complexity should be less than O(n2).
  4. There is only one duplicate number in the array, but it could be repeated more than once.


-------------------------------------------------------------分割线----------------------------------------------------------

给定一个长度为n+1的数组,里面包含的数范围在[1,n]。证明这个数组里面必有重复的数字(抽屉原理)。
假定数组里面仅有一个重复的数字,要求找出这个重复的数字。
其他要求包括:输入数组只读(不可改变),O(1)空间复杂度,小于O(n^2)的时间复杂度,重复的数字可以出现多于2次。

分析:
amazing 啊! 一道非常有分量的题目,题设简单,但是为了追求更优解是值得花时间的!

1. 最暴力的解法就是直接穷举,但是时间复杂度是O(n^2),不满足题意。

2. 要把时间复杂度降下来,很自然就能想到O(nlogn)的二分查找,在[1,n]范围内用二分枚举答案,记为mid。遍历数组,如果比mid小的数字超过mid个,那答案就会落在[1,mid];否则,则答案落在(mid,n];解法也没什么难度,也好理解,直接上代码把:

class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        
        int len = nums.size()-1;
        int right = len, left = 1;
        int mid,count;
        
        while (left < right){
            mid = (left + right) / 2;
            count = 0;
            for (int i = 0; i < len+1 ; i ++) 
                if (nums[i] <= mid) count++;
            
            if (count > mid) right = mid;
            else left = mid + 1;
        }
        
        return left;
    }
};

3. 实在想不到…这题真的还能有O(n)复杂度的解法。使用的是快慢指针的思想,原理我直接贴我看的题解和帖子吧,不再赘述一遍。

解法用到了快慢指针找链表闭环问题的思想( http://bookshadow.com/weblog/2015/07/10/leetcode-linked-list-cycle-ii/

针对这道题的这个构造简直惊为天人!

英文看得晕的,还有一个中文翻译版的:

学习了学习了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值