题目描述:
You have a read-only array A[1..n] which is populated by numbers from 1..n-1, which implies atleast one repetition. However, there can be more. Find any one repeated number in linear time O(n) using constant space.
思路分析:
1、如果数组中有且仅有一个重复数,可以简单的通过S(A)-(n-1)*n/2得到重复数,其中S(A)表示对数组A求和
代码略
2、仿链表中找环的思路解决至少含一个重复数的问题
// int x = n, y = n;
// do {x = A[A[x]]; y = A[y];} while (x!=y);
// x = n;
// do {x = A[x]; y = A[y];} while (x!=y);
// return x;
从尾部开始操作,避免了A[1]恰好等于1从而陷入死循环,因为在最大元素为n-1的数组中,A[n]不可能等于n
The first 'do' finds the cycle but it does not tell where we entered it. And it is only at the entry point that we have a repeat. The second 'do' uses information about the cycle length to find the place where we entered the loop.
例子:
// Ex.
// 1,2,1,4,4
// int x = n, y = n;
// <x=5, y=5>
//
// do {x = A[A[x]]; y = A[y];
// <x=4, y=4>
// } while (x!=y);
// <x=4, y=4>
//
// x = n;
// <x=5, y=4>
//
// do {x = A[x]; y = A[y];
// <x=4, y=4>
// } while (x!=y);
// <x=4, y=4>
//
// return x;
// <x=4>
代码实现:
#include <iostream>
using namespace std;
////含n个元素的序列中至少有一个元素重复,并且每个元素取值在[1,n-1]之间
// int x = n, y = n;
// do {x = A[A[x]]; y = A[y];} while (x!=y);
// x = n;
// do {x = A[x]; y = A[y];} while (x!=y);
// return x;
// Ex.
// 1,2,1,4,4
// int x = n, y = n;
// <x=5, y=5>
//
// do {x = A[A[x]]; y = A[y];
// <x=4, y=4>
// } while (x!=y);
// <x=4, y=4>
//
// x = n;
// <x=5, y=4>
//
// do {x = A[x]; y = A[y];
// <x=4, y=4>
// } while (x!=y);
// <x=4, y=4>
//
// return x;
// <x=4>
int FindRepetitionNumber(int seq[],int n)
{
int x=n;
int y=n;
////第一次循环找相遇点
do
{
x=seq[seq[x-1]-1];
y=seq[y-1];
}
while(x!=y);
////第二次循环确定重复的那个数
x=n;
do
{
x=seq[x-1];
y=seq[y-1];
}
while(x!=y);
return x;
}
int _tmain(int argc, _TCHAR* argv[])
{
int n=6;
int rep[7]={3,2,5,4,1,3,6}; //////n个介于[1,n-1]的元素
cout<<"重复元素 : "<<FindRepetitionNumber(rep,n)<<endl;
system("pause");
return 0;
}