题目
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.
Example 1:
Input: [1,3,4,2,2]
Output: 2
Example 2:
Input: [3,1,3,4,2]
Output: 3
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.
分析
-
如果把数组里的数同时看成是索引的话,那么这就是一个典型的链表结构,即从一个数可以得到下一个数
-
类比202.快乐数也是从一个数根据某种规则生成下一个数,从而得到一个链表结构
-
如果数组里面的数有重复,那么得到的就是一个带环的链表结构,并且环的第一个元素就是重复的数字
具体做法可以参考142.环形链表 II
代码和注释
int findDuplicate(int* nums, int numsSize){
int p, q; //定义p,q两个快慢指针
p = q = nums[0]; // 初始化快慢指针在同一位置,都为nums[0]
do {
p = nums[p]; // 慢指针p走一步
q = nums[nums[q]]; //快指针q走两步
}while (p != q);
//求环的长度
int length = 0;
do {
p = nums[p];
length++;
} while (p != q);
//先让一个指针走一个环的长度
p = q = nums[0];
while (length--) {
p = nums[p];
}
//再让另一个指针开始走,直到相遇
while (p != q) {
p = nums[p];
q = nums[q];
}
return p;
}