leetcode 287 Find the Duplicate Number
2016-03-13 13:21
344 查看
原题:
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:
You must not modify the array (assume the array is read only).
You must use only constant, O(1) extra space.
Your runtime complexity should be less than
There is only one duplicate number in the array, but it could be repeated more than once.
题意:有n+1个数字,范围从1到n,其中有一个数字会重复多次,用低于O(n2)的时间复杂度算法找出重复的数字,空间复杂的为O(1)。
解法:没有这些条件限制,就可以用二重循环直接找出来,或者用set/map等容器来做,正是由于这些条件限制,这题才变得有意思起来。
很不幸我没有独立解决出这道题,看题解都看了半天才明白,所以一定要用烂笔头记下来。
解法一:思路是采用了二分法+抽屉远离。首先解释一下为什么用二分法,因为O(n2)时间复杂度不能A,所以往下应该是n*logn,很容易联想到二分法,因为其复杂度为logn。
抽屉原理是说假设你有11个苹果,要放进10个抽屉,那么至少有一个抽屉里是有两个苹果的。
对应到这题,1~n的n+1个数字,有1个数字会至少重复两次。
比如取数组为{1,2,2,3,4,5},一共6个数,范围是1~5,其中位数应该是(5+1)/2 = 3,那么,如果小于等于3的数的个数如果超过了3,那么重复的数字一定出现在[1,3]之间,否则出现在[4,5]之间。以该数组为例,中位数为3,小于等于3的数一共有4个,大于3的数有两个,所以重复的数字在[1,3]之间。
代码:
解法二:
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:
You must not modify the array (assume the array is read only).
You must use only constant, O(1) extra space.
Your runtime complexity should be less than
O(n2).
There is only one duplicate number in the array, but it could be repeated more than once.
题意:有n+1个数字,范围从1到n,其中有一个数字会重复多次,用低于O(n2)的时间复杂度算法找出重复的数字,空间复杂的为O(1)。
解法:没有这些条件限制,就可以用二重循环直接找出来,或者用set/map等容器来做,正是由于这些条件限制,这题才变得有意思起来。
很不幸我没有独立解决出这道题,看题解都看了半天才明白,所以一定要用烂笔头记下来。
解法一:思路是采用了二分法+抽屉远离。首先解释一下为什么用二分法,因为O(n2)时间复杂度不能A,所以往下应该是n*logn,很容易联想到二分法,因为其复杂度为logn。
抽屉原理是说假设你有11个苹果,要放进10个抽屉,那么至少有一个抽屉里是有两个苹果的。
对应到这题,1~n的n+1个数字,有1个数字会至少重复两次。
比如取数组为{1,2,2,3,4,5},一共6个数,范围是1~5,其中位数应该是(5+1)/2 = 3,那么,如果小于等于3的数的个数如果超过了3,那么重复的数字一定出现在[1,3]之间,否则出现在[4,5]之间。以该数组为例,中位数为3,小于等于3的数一共有4个,大于3的数有两个,所以重复的数字在[1,3]之间。
代码:
int findDuplicate(vector<int>& nums) { int low = 1, high = nums.size()-1; //low和high为数字的取值范围 while(low<high) { int cnt = 0; //cnt为不大于中位数的数字个数 int mid = (low + high)/2; for(int i=0;i<nums.size();i++) { if(nums[i] <= mid) cnt++; } if(cnt>mid) { high = mid; //如果不大于mid的数字个数比mid多的话,则重复数字应该出现在[low, mid]之间 } else low = mid+1; //如果不大于mid的数字个数比mid少的话,说明重复的数字出现在后半段中[mid+1,high] } return low; }
解法二:
相关文章推荐
- nyoj--61 传字条(一)(多线程dp)
- linux使用dhclient自动获取IP
- opencv haartraining训练过程总结dir /b > info.txt
- hdoj 又一版 A+B 1877 (机制转换)
- 变量、作用域和内存问题
- hdoj--2187--悼念512汶川大地震遇难同胞——老人是真饿了(贪心)
- linux常用命令
- Problem G: C语言习题 n个数逆序
- 变量和函数的作用域、链接属性、存储范围
- 实验三:跟踪分析Linux内核的启动过程 ----- 20135108 李泽源
- LintCode: Maximum Depth of Binary Tree
- hdoj--2187--悼念512汶川大地震遇难同胞——老人是真饿了(贪心)
- Reactor
- 动漫迷看的一点动漫
- Linux Shell 1>/dev/null 2>&1 含义
- 前言
- HQL执行的三种方式
- 剑指offer-复杂链表的复制
- ICMP协议
- dz会员找回密码提示参数错误的解决方案