当前位置:   article > 正文

287寻找重复数(Floyd判圈算法、二分查找)_弗洛伊德判环那个重复的数是什么

弗洛伊德判环那个重复的数是什么

1、题目描述

给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设只有一个重复的整数,找出这个重复的数。

说明:

  • 不能更改原数组(假设数组是只读的)。
  • 只能使用额外的 O(1) 的空间。
  • 时间复杂度小于 O(n2) 。
  • 数组中只有一个重复的数字,但它可能不止重复出现一次。

2、示例

输入: [1,3,4,2,2]
输出: 2

3、题解

解法一:

基本思想:快慢指针,Floyd判圈算法,时间复杂度O(n)空间复杂度O(1)

假设环长为 L,从起点到环的入口的步数是 a,从环的入口继续走 b 步到达相遇位置,从相遇位置继续走 c 步回到环的入口,则有 b+c=L,其中 L、a、b、c 都是正整数。根据上述定义,慢指针走了 a+b 步,快指针走了 2(a+b) 步。从另一个角度考虑,在相遇位置,快指针比慢指针多走了若干圈,因此快指针走的步数还可以表示成 a+b+kL,其中 kk表示快指针在环上走的圈数。联立等式,可以得到:2(a+b)=a+b+kL

解得 a=kL-b,整理可得:a=(k-1)L+(L-b)=(k-1)L+c

从上述等式可知,如果慢指针从起点出发,快指针从相遇位置出发,每次两个指针都移动一步,则慢指针走了 a 步之后到达环的入口,快指针在环里走了 k-1 圈之后又走了 c 步,由于从相遇位置继续走 c 步即可回到环的入口,因此快指针也到达环的入口。两个指针在环的入口相遇,相遇点就是答案。

解法二:

基本思想:二分查找,时间复杂度O(nlongn)空间复杂度O(1)
        arr = [1,3,4,2,2] 此时数字在 1 — 5 之间
        mid = (1 + 5) / 2 = 3 arr小于等于的3有4个(1,2,2,3),1到3中肯定有重复的值
        mid = (1 + 3) / 2 = 2 arr小于等于的2有3个(1,2,2),1到2中肯定有重复的值
        mid = (1 + 2) / 2 = 1 arr小于等于的1有1个(1),2到2中肯定有重复的值
        所以重复的数是 2

  1. #include<iostream>
  2. #include<vector>
  3. #include<algorithm>
  4. using namespace std;
  5. class Solution {
  6. public:
  7. int findDuplicate(vector<int>& nums) {
  8. //基本思想:快慢指针,Floyd判圈算法,时间复杂度O(n)空间复杂度O(1)
  9. int slow=0,fast=0;
  10. while(true)
  11. {
  12. slow=nums[slow];
  13. fast=nums[nums[fast]];
  14. if(slow==fast)
  15. break;
  16. }
  17. slow=0;
  18. while(slow!=fast)
  19. {
  20. slow=nums[slow];
  21. fast=nums[fast];
  22. }
  23. return fast;
  24. }
  25. };
  26. class Solution1 {
  27. public:
  28. int findDuplicate(vector<int>& nums) {
  29. //基本思想:二分查找
  30. /*
  31. arr = [1,3,4,2,2] 此时数字在 1 — 5 之间
  32. mid = (1 + 5) / 2 = 3 arr小于等于的3有4个(1,2,2,3),1到3中肯定有重复的值
  33. mid = (1 + 3) / 2 = 2 arr小于等于的2有3个(1,2,2),1到2中肯定有重复的值
  34. mid = (1 + 2) / 2 = 1 arr小于等于的1有1个(1),2到2中肯定有重复的值
  35. 所以重复的数是 2
  36. */
  37. int n = nums.size();
  38. int l = 1, r = n - 1, res;
  39. while (l <= r) {
  40. int mid = l +(r - l)/2;
  41. int cnt = 0;
  42. for (int i = 0; i < n; ++i) {
  43. if(nums[i] <= mid)
  44. cnt++;
  45. }
  46. if (cnt <= mid) {
  47. l = mid + 1;
  48. } else {
  49. r = mid - 1;
  50. res = mid;
  51. }
  52. }
  53. return res;
  54. }
  55. };
  56. int main()
  57. {
  58. Solution solute;
  59. vector<int> nums={1,3,4,2,2};
  60. cout<<solute.findDuplicate(nums)<<endl;
  61. return 0;
  62. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/500354
推荐阅读
相关标签
  

闽ICP备14008679号