寻找重复数 中等

算法二十天

第九天

寻找重复数
给定一个包含 n + 1 个整数的数组 nums ,其数字都在 [1, n] 范围内(包括 1 和 n),可知至少存在一个重复的整数。

假设 nums 只有 一个重复的整数 ,返回 这个重复的数 。

你设计的解决方案必须 不修改 数组 nums 且只用常量级 O(1) 的额外空间。

示例 1:

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

示例 2:

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

提示:

1 <= n <= 10^5
nums.length == n + 1
1 <= nums[i] <= n
nums 中 只有一个整数 出现 两次或多次 ,其余整数均只出现 一次

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-the-duplicate-number

首先想到的是利于哈希表记录每个数字的出现个数,如果大于1返回,但是空间复杂度为O(n),不符合题意。这里的数组很特别,num[i]<=n,n.length==n+1所以可以将数组中的数当成指针,譬如{1,3,2,1},nums[0]中是下一个数的地址,依次类推,最后总会有环出现请添加图片描述
于是问题转化成了求链表中是否有环并且判断环的入口

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

2(a+b)=a+b+kL 2(a+b)=a+b+kL

解得 a=kL-ba=kL−b,整理可得

a=(k-1)L+(L-b)=(k-1)L+c a=(k−1)L+(L−b)=(k−1)L+c

作者:LeetCode-Solution
链接:https://leetcode-cn.com/problems/find-the-duplicate-number/solution/xun-zhao-zhong-fu-shu-by-leetcode-solution/ 来源:力扣(LeetCode)

所以当slow指针从起点开始走的化再次相遇即是入口,这道题很难想到这mo巧的答案,毕竟题目的条件很巧合。

#include<bits/stdc++.h>
using namespace std; 


int f(vector<int>& temp) {
    
    
	int slow=temp[0];
	int fast=temp[temp[0]];
	while(slow!=fast)
	{
    
    
		slow=temp[slow];
		fast=temp[temp[fast]];
	}
	slow=0;
	while (slow != fast) {
    
    
            slow = temp[slow];
            fast = temp[fast];
        }
        return slow;
}
int main()
{
    
    
	vector<int> temp={
    
    1,3,4,2,5,2,6,7};
	cout<<f(temp);
}

猜你喜欢

转载自blog.csdn.net/BeiWoFW/article/details/124261861
今日推荐