Algoritmo de la liebre y la tortuga de Floyd (algoritmo del círculo del juicio de Freud)

El algoritmo de detección de círculos de Floyd (Robert Floyd) (Algoritmo de detección de ciclos de Floyd), también conocido como Algoritmo de tortuga y liebre (Algoritmo de tortuga y liebre), es una máquina de estado finito, una función iterativa o una lista vinculada para determinar si hay anillos y un algoritmo para determinar el punto de partida y la longitud del anillo.

Me encontré con un video anoche, Joma Tech de Youtube. El video en sí es muy interesante. Por supuesto, este amigo también es muy interesante. A menudo publica videos en Youtube y renunció a FB. Ahora trabaja en Google.

Presenta cómo implementar el siguiente algoritmo, principalmente porque el contenido del video es muy interesante. Por supuesto, aquí hay algunos algoritmos que aparecen en él.

Tema: Encuentra los números repetidos en la matriz. Solo hay un número repetido en la matriz, que se puede repetir muchas veces. El requisito del algoritmo es que la complejidad del tiempo sea menor que O(n²), y la complejidad del espacio sea O(1)

El problema es muy simple y hay muchas maneras de resolverlo. Hay una búsqueda de bucle directo. Para mejorar la eficiencia, también puede usar la búsqueda binaria. Los dos primeros métodos en el video son los siguientes:

Después de ordenar, los elementos adyacentes son números duplicados si son iguales. Sin embargo, la complejidad del tiempo de ejecución es alta y requiere mucho tiempo. ¡No puedo pasar!

def findDuplicate1(nums):
  nums.sort()
  for i in range(1,len(nums)):
    if nums[i]==nums[i-1]:
      return nums[i]

arr1=[1,3,4,2,2]
arr2=[8,1,3,4,2,4,5,4]

print(findDuplicate1(arr1))#2
print(findDuplicate1(arr2))#4

Use un diccionario o conjunto para guardar el valor en la matriz transversal y luego juzgue si se ha agregado. Si se agrega, significa que el valor se repite.

Aunque este método acorta el tiempo en comparación con el método anterior, la complejidad del espacio aumenta y consume más memoria. ¡No puedo pasar!

def findDuplicate2(nums):
  seen={}
  for num in nums:
    if num in seen:
      return num
    seen[num]=True

print(findDuplicate2(arr1))#2
print(findDuplicate2(arr2))#4

#或者set()也可以
def findDuplicate2_(nums):
  seen=set()
  for num in nums:
    if num in seen:
      return num
    seen.add(num)
print(findDuplicate2_(arr1))#2
print(findDuplicate2_(arr2))#4

A continuación, mire el algoritmo que cumple con los requisitos, que es el algoritmo de tortuga y conejo que se presenta a continuación.

Por supuesto, todavía hay una restricción en este tema. Dada una matriz nums que contiene n + 1 enteros, cada uno de los cuales está entre 1 y n (inclusive) , de lo contrario, el ejemplo que di mostrará que el índice está fuera de los límites. de esta forma se puede usar el algoritmo de la tortuga y la liebre, y algunas personas lo llaman puntero de velocidad, y se forma un lazo cerrado si hay repetición:

def findDuplicate_ok(nums):
  tortoise=nums[0]
  hare=nums[0]
  while True:
    tortoise=nums[tortoise]#龟
    hare=nums[nums[hare]]#兔
    if tortoise==hare:
      break
  
  ptr1=nums[0]
  ptr2=tortoise
  while ptr1!=ptr2:
    ptr1=nums[ptr1]
    ptr2=nums[ptr2]
  return ptr1

arr1=[1,3,4,2,2]
arr3=[1,4,6,8,2,3,8,5,7]
print(findDuplicate_ok(arr1))#2
print(findDuplicate_ok(arr3))#8

Complejidad temporal: O(n), complejidad espacial: O(1)

Por supuesto, si eres un principiante, te sentirás un poco complicado. No importa. Podemos establecer un punto de ruptura en la posición de la tortuga (o conejo o ambos) , y luego paso a paso, y entenderemos el proceso de ejecución de todo el algoritmo paso a paso. Este es también el método más común y efectivo que todos necesitan para depurar o comprender los cambios de algunas variables.

Si no es conveniente depurar, también publicaré todo el proceso de ejecución para una fácil observación:

Matriz: números = [1,4,6,8,2,3,8,5,7]

2do

la tercera vez

4to

5to

tortuga

números[0] = 1

numeros[ 1 ]= 4

números[ 4 ]= 2

numeros[2]=6

numeros[6]=8

conejo

números[0] = 1

números[ números[1] ]= 2

números[ números[2] ]=8

numeros[7]=5

numeros[3]=8

Al iterar a la quinta vez, los dos son iguales, así que salga del ciclo y luego encuentre el valor repetido a través del puntero.

ptr1=1

numeros[1]=4

numeros[4]=2

numeros[2]=6

numeros[6]=8

ptr2=8

numeros[8]=7

numeros[7]=5

numeros[5]=3

numeros[3]=8

Supongo que te gusta

Origin blog.csdn.net/weixin_41896770/article/details/129681143
Recomendado
Clasificación