题目
这里要注意,假设了只有一个重复整数,大概就是[1,2,3,4,4]/[1,2,2,3,4]/[2,2,2,2]这样,然后可能是乱序的。
思路一 排序
排序之后重复的元素肯定是连在一起的,遍历然后保存上一个遍历的元素判断是否重复即可
1 | function findDuplicate(nums) { |
思路二 出现次数
哈希表记录
虽然LeetCode上可运行,但这个应该是不符合O(1)的空间复杂度的
1 | var findDuplicate = function(nums) { |
利用数据特性
以上数据有一个特性,比如输入的[1,3,4,2,2],总结出下表
元素 | count |
---|---|
1 | 1 |
2 | 3 |
3 | 4 |
4 | 5 |
其中出现的元素有1,2,3,4,count则代表小于等于该元素的元素个数,比如小于等于1的元素只有1(1个),小于等于2的元素有1,2,2(3个)。由于整数的范围是[1,n],所以只要出现了元素,count就等于元素数值,出现了重复元素count就会大于元素数值,又由于题目给出数据只存在一个重复多次的元素,那么只要找到第一个count>元素数值的元素即可。
普通遍历
1 | function findDuplicate(nums) { |
二分查找
1 | function findDuplicate(nums) { |
快慢指针
由于存在的重复的数字 target,因此 target 这个位置一定有起码两条指向它的边,因此整张图一定存在环,且我们要找到的 target 就是这个环的入口。
我们先设置慢指针 slow 和快指针 fast ,慢指针每次走一步,快指针每次走两步,直到两个指针相遇,此时我们再将 slow 设为 0,两个指针每次移动一步,再次相遇的点就是答案。
这里简单解释为什么后面将 slow 放置起点后移动相遇的点就一定是答案了。如图:
假设起点到环入口距离为a,环长为L,相遇点到环入口为b,环剩余部分为c,则有则慢指针走了a+c,快指针走了a+c+kL,其中k是圈数未知。由于慢指针走一步,快指针走两步,快指针走的距离也可以为2(a+c),得出等式 2(a+c) = a+c+kL。解得 a = kL - c, 倒退一圈可以变成a= (k-1)L + (b+c) -c,化简可得a=(k-1)L+b,很明显如果慢指针从0开始走到环入口(a),快指针同时一步一步移动,会走k-1圈,并多走b步到达环入口,而环入口则是我们重复的元素,即可得出答案。
1 | function findDuplicate(nums) { |