Find the Duplicate Number
来源:互联网 发布:大数据广告精准投放 编辑:程序博客网 时间:2024/05/16 07:09
问题描述:
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.
这个问题不是很难,但是如果将时间复杂度限制了,就对算法有很高的要求。
首先,我们先抛开时间复杂度的要求,这样就会很容易的想到三个解法:
1、暴力破解O(n^2)这个不解释
2、稍微复杂一点,首先利用快速排序,得到一个有序序列,然后就可以遍历出duplicate element了。复杂度O(nlogn)。
3、利用二分查找的思想:
由于数组中的元素只有一个是有重复的,那么对于任意一个元素k,如果比k小的元素的个数为k-1(1~k-1),那么在k之前一定没有重复的元素,则我们就向后查找,否则就
向前查找。这个的时间复杂度也是O(nlogn)。
看起来似乎不太可能有更简单的解法了,非也。这个解法可是困扰了大神唐纳德·克努特24小时,所以咱常人想不到也是正常的。
下面直入主题吧,我们怎么做到时间复杂度O(n),空间复杂度O(1),的呢?
我们首先建立一下模型:
1、链表模型,
我们把数组A = {1,2,3...,n},建立一个映射,并且射到它自己。f(i) = A[i]-1,下面问题就变为了在i != j 的情况下,找到一对(i,j)使得f(i)==f(j)。下图为对链表建立的模型。
x_0 = n;
x_ 1 = f(x_0);
x_2 = f(x_1);
...........
x_k = f(x_k-1);
我们可以看到当转化成为链表模型之后我们只需要找到链表的入口,就可以找到重复的元素了。
但是,这只是一个大体的思路,我在做的时候有过几个思考。
1)对于A={1,2,3,2}来说,我们在按照链表索引的时候f(2) = A[2] - 1 = 3 - 1 = 2; 然后 就在这里不断循环,因为它是指向它自己的。那么此时算法会不会失效?
答案是:不会。因为当指向自己的元素不是重复元素的时候,也就是说它只会出现一次,那么不会有元素指向它(因为它已经指向了自己),所以它不会出现在链表
中,如果它是重复的元素,那么也不会对算法产生影响,因为此时只能访问到重复的元素。
2)为什么要从n开始?
因为我们元素的范围是1~n,f(i)= A[i] - 1;也就是说如果从前面开始无法访问到位置为n的元素。
2、找到链表入口
此时我们可以仅仅在链表模型上面考虑如何找到链表入口。
我们从链表头开始,假设从链表头到链表入口的距离为C,链表长度为L。有两个指针遍历链表,一个是快指针,一个是慢指针,慢指针一次移动一个节点,快指针的速度是慢指针的两倍。
考虑当两个指针相遇时。第一次相遇的点一定是mL,且(m-1)L < C , mL >= C。 因为当前进的不够C的时候,还没有进入环,不会相遇,进入环以后,慢指针的位置为p,快指针前进了2mL,在mL的位置上又绕了环走了m圈,则位置还是在p上。
现在快指针不动了,另外一个慢指针从头开始走,p位置上的慢指针随着它一起动,两个指针就会在环的入口处相遇。
因为在入口处,新指针前进了C = mL - p ,而慢指针前进了相同的距离。所以慢指针的位置是mL - p + p = mL 在环的起点处。
现在我们找到了入口节点,也就是说找到了一对(i,j) i != j。有f(i) ==f(j)。即找到了这个重复的元素,时间复杂度也为O(n)。
参考文献:http://keithschwarz.com/interesting/code/?dir=find-duplicate
- Find the Duplicate Number
- Find the Duplicate Number
- Find the Duplicate Number
- Find the Duplicate Number
- Find the Duplicate Number
- Find the Duplicate Number
- Find the Duplicate Number
- Find the Duplicate Number
- Find the Duplicate Number
- Find the Duplicate Number
- Find the Duplicate Number
- Find The Duplicate Number
- Find the Duplicate Number
- Find the Duplicate Number
- Find the Duplicate Number
- Find the Duplicate Number
- Find the Duplicate Number
- Find the Duplicate Number
- 黑马程序员-多线程部分(一.创建)
- 关于UITextView的几种回收键盘的方法
- 升级Xcode之后插件不能
- 数据结构_线性结构_栈与队列
- iOS 动画基础
- Find the Duplicate Number
- k-近邻算法
- WORD里表格复制到另一WORD里表格会变形的解决办法
- JAVA笔记(四)
- c# 数据类型占用的字节数
- HDU5501
- 日本推出无人菜园,大量工人失业不远了
- http请求状态
- J2SE 抽象类,接口