思路:
数字的范围是1-n,数组的下标范围是0-n,所以必定存在重复的数字。
将下标对应的数字作为当前数字的下一个数字,这样就得到了一个类似链表的结构。
转化为了题目142. 环形链表 II-CSDN博客找到链表环的入口。
总结:
也可以使用二分答案的方法,对于每一个mid,遍历一遍数组找到小于等于mid的个数cnt,如果cnt = mid,说明[ l , mid ]区间没有重复的元素,答案在[ mid + 1, r ],否则说明重复的元素在[ l, mid ]中。
代码:
方法1:环形链表
class Solution {
public int findDuplicate(int[] nums) {
int slow = 0, fast = 0;
slow = nums[slow];
fast = nums[nums[fast]];
while(slow != fast) {
slow = nums[slow];
fast = nums[nums[fast]];
}
slow = 0;
while(slow != fast) {
slow = nums[slow];
fast = nums[fast];
}
return slow;
}
}
方法2:二分答案
class Solution {
public int findDuplicate(int[] nums) {
int n = nums.length;
int l = 1, r = n - 1;
while(l <= r) {
int mid = l + (r - l)/2;
// l 右边都是出现次数大于mid的
if(check(mid, nums) > mid) {
r = mid - 1;
}
// r 左边出现次数都是小于等于mid的
else {
l = mid + 1;
}
}
return l;
}
private int check(int t, int[] nums) {
int cnt = 0;
for(int num : nums) {
if(num <= t) cnt++;
}
return cnt;
}
}
参考: