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个数,其中有一个数是重复的,求那个重复的数。
如图所示:
此题分为两个steps
1.第一次相遇的时候,2m = m+c*r-------->m=c*r@;
n+a=m@
结合起来就是n+a=c*r------>n=c*r-a------>n=(c-1)*r+r-a;
2.通过之前的公式可以知道,把其中一个指针重置为起点后,而另一个指针不变,每次移动一步,那么下一次相遇的地点就是入口处,而本题数组循环的入口处是肯定为重复数字的,因此问题解决了,代码如下:
1 public class Solution { 2 public int findDuplicate(int[] nums) { 3 //we set the slow and fast pointer to the index of 0,so that they could reach in the same loop 4 int slow = nums[0]; 5 int fast = nums[nums[0]]; 6 //find the meeting point in the loop 7 while(slow!=fast){ 8 slow = nums[slow]; 9 fast = nums[nums[fast]]; 10 } 11 //find the entry loop point 12 fast = 0; 13 while(slow!=fast){ 14 slow = nums[slow]; 15 fast = nums[fast]; 16 } 17 return slow; 18 } 19 } 20 //the run time could be less than O(n);the space complexity coud be O(1);
此题也是说明了一点,即起点设为哪一点都可以,最终的结果都不受影响
1 public class Solution { 2 public int findDuplicate(int[] nums) { 3 int low = 1; 4 int high = nums.length-1; 5 while( low < high ) { 6 int count = 0; 7 int mid = low + ( high - low ) / 2; 8 for(int i=0;i<nums.length;i++){ 9 if(nums[i]<=mid) count++; 10 } 11 if(count<=mid) low = mid+1; 12 else high = mid; 13 } 14 return low; 15 } 16 } 17 // the run time complexity could be O(nlogn) ,the space complexity could be O(1);