给定一个大小为N + 1的只读数组arr[] ,找到数组中多个重复元素之一,其中数组仅包含1和N之间的整数。
注意:只读数组意味着数组的内容不能被修改。
例子:
Input: N = 5, arr[] = {1, 1, 2, 3, 5, 4}
Output: 1
Explanation:
1 is the only number repeated in the array.
Input: N = 10, arr[] = {10, 1, 2, 3, 5, 4, 9, 8, 5, 6, 4}
Output: 5
Explanation:
5 is the one of the number repeated in the array.
在上一篇文章中,我们讨论了空间复杂度为O(N) 和 O(sqrt(N))的同一篇文章。
方法:这种方法基于弗洛伊德的龟兔赛跑算法( Cycle Detection Algorithm )。
- 使用函数f(x) = arr[x]构造序列:
arr[0], arr[arr[0]], arr[arr[arr[0]]], arr[arr[arr[arr[0]]]] …….
- 序列中的每个新元素都是arr[]中前一个元素索引处的一个元素。
- 从x = arr[0] 开始,它会产生一个带循环的链表。
- 循环出现是因为arr[]包含重复元素(至少一个)。重复值是循环的入口。下面给出了一个例子来说明循环是如何存在的:
例如:让数组 arr[] = {2, 6, 4, 1, 3, 1, 5}
index | 0 | 1 | 2 | 3 | 4 | 5 | 6 |
---|---|---|---|---|---|---|---|
arr | 2 | 6 | 4 | 1 | 3 | 1 | 5 |
从索引 0 开始,遍历如下所示:
arr[0] = 2 –> arr[2] = 4 –> arr[4] = 3 –> arr[3] = 1 –> arr[1] = 6 –> arr[6] = 5 –> arr[5] = 1.
序列形成循环如下图:
- 算法由两部分组成并使用两个指针,通常称为tortoise和hare 。
- hare = arr[arr[hare]]是tortoise = arr[tortoise] 的两倍。
- 由于兔子跑得很快,它会是第一个进入循环并开始绕着循环跑的人。
- 在某些时候,乌龟也会进入循环,由于它移动得较慢,兔子在某个交叉点抓住了乌龟。
- 请注意,在一般情况下,交点不是循环入口,而是两者在循环中间的某个地方相交。
- 将乌龟移动到序列的起点,兔子保持在循环内,并且以相同的速度移动,即tortoise = arr[tortoise]和hare = arr[hare] 。现在它们在重复元素处相交。
下面是上述方法的实现:
C++
// C++ code for the above approach
#include
using namespace std;
// Function to find the duplicate
// value in the given array arr[]
void findDuplicate(int arr[])
{
// Initialise variables
int tortoise = arr[0];
int hare = arr[0];
// Loop till we find the
// duplicate element
while (1) {
tortoise = arr[tortoise];
// Hare moves with twice
// the speed of tortoise
hare = arr[arr[hare]];
if (tortoise == hare)
break;
}
tortoise = arr[0];
// Loop to get start point
// of the cycle as start
// point will be the duplicate
// element
while (tortoise != hare) {
tortoise = arr[tortoise];
hare = arr[hare];
}
// Print the duplicate element
cout << tortoise;
}
// Driver Code
int main()
{
// Given array
int arr[] = { 2, 6, 4, 1, 3, 1, 5 };
// Function Call
findDuplicate(arr);
return 0;
}
Java
// Java code for the above approach
class GFG{
// Function to find the duplicate
// value in the given array arr[]
static void findDuplicate(int arr[])
{
// Initialise variables
int tortoise = arr[0];
int hare = arr[0];
// Loop till we find the
// duplicate element
while (true)
{
tortoise = arr[tortoise];
// Hare moves with twice
// the speed of tortoise
hare = arr[arr[hare]];
if (tortoise == hare)
break;
}
tortoise = arr[0];
// Loop to get start point
// of the cycle as start
// point will be the duplicate
// element
while (tortoise != hare)
{
tortoise = arr[tortoise];
hare = arr[hare];
}
// Print the duplicate element
System.out.print(tortoise);
}
// Driver Code
public static void main (String []args)
{
// Given array
int arr[] = { 2, 6, 4, 1, 3, 1, 5 };
// Function Call
findDuplicate(arr);
}
}
// This code is contributed by chitranayal
Python3
# Python3 program for the above approach
# Function to find the duplicate
# value in the given array arr[]
def findDuplicate(arr):
# Initialise variables
tortoise = arr[0]
hare = arr[0]
# Loop till we find the
# duplicate element
while (1):
tortoise = arr[tortoise]
# Hare moves with twice
# the speed of tortoise
hare = arr[arr[hare]]
if (tortoise == hare):
break
tortoise = arr[0]
# Loop to get start point
# of the cycle as start
# point will be the duplicate
# element
while (tortoise != hare):
tortoise = arr[tortoise]
hare = arr[hare]
# Print the duplicate element
print (tortoise)
# Driver Code
# Given array
arr = [ 2, 6, 4, 1, 3, 1, 5 ]
# Function Call
findDuplicate(arr)
# This code is contributed by PratikBasu
C#
// C# program for the above approach
using System;
class GFG{
// Function to find the duplicate
// value in the given array []arr
static void findDuplicate(int []arr)
{
// Initialise variables
int tortoise = arr[0];
int hare = arr[0];
// Loop till we find the
// duplicate element
while (true)
{
tortoise = arr[tortoise];
// Hare moves with twice
// the speed of tortoise
hare = arr[arr[hare]];
if (tortoise == hare)
break;
}
tortoise = arr[0];
// Loop to get start point
// of the cycle as start
// point will be the duplicate
// element
while (tortoise != hare)
{
tortoise = arr[tortoise];
hare = arr[hare];
}
// Print the duplicate element
Console.Write(tortoise);
}
// Driver Code
public static void Main(String []args)
{
// Given array
int []arr = { 2, 6, 4, 1, 3, 1, 5 };
// Function Call
findDuplicate(arr);
}
}
// This code is contributed by Amit Katiyar
Javascript
1
时间复杂度: O(N)
辅助空间: O(1)
如果您希望与专家一起参加现场课程,请参阅DSA 现场工作专业课程和学生竞争性编程现场课程。