Estructura de datos y algoritmo: ¿cómo juzgar una lista enlazada individualmente como una lista enlazada?

Juzgar si una lista enlazada individualmente es una lista enlazada es una pregunta clásica en informática, y también es un punto de inspección común en las entrevistas. Antes de resolver este problema, debemos comprender la definición de lista enlazada simple y lista enlazada en anillo y sus características.

1. Definición y características de la lista enlazada simple

La lista de enlaces individuales es una estructura de datos común, que consiste en una serie de nodos (Nodo), cada nodo contiene dos partes: campo de datos (datos de almacenamiento) y campo de puntero (que apunta al siguiente nodo). El puntero del último nodo de la lista enlazada individualmente apunta a un valor nulo (nulo), lo que indica el final de la lista enlazada.

La característica de una lista enlazada simple es que los nodos están conectados en una dirección, es decir, cada nodo solo puede apuntar al siguiente nodo y no puede apuntar al nodo anterior. Esta función hace que el recorrido de la lista enlazada individual comience desde el nodo principal y visite cada nodo uno por uno hasta llegar al final de la lista enlazada.

Por ejemplo, aquí hay un ejemplo de una lista simple enlazada:

1 -> 2 -> 3 -> 4 -> null

Entre ellos, 1 es el nodo de cabeza, 4 es el nodo de cola y la flecha indica la dirección hacia la que apunta.

2. Definición y características de lista enlazada

Una lista vinculada significa que hay uno o más nodos en la lista vinculada para formar un anillo, y el último nodo apunta a un nodo anterior en la lista vinculada en lugar de nulo. Una lista enlazada también se conoce como lista enlazada circular o lista enlazada circular.

Por ejemplo, aquí hay un ejemplo de una lista enlazada:

1 -> 2 -> 3 -> 4 -> 2

En este ejemplo, el nodo 2 apunta al nodo anterior al 3, formando un anillo.

El problema de juzgar si una lista enlazada individualmente es una lista enlazada se puede transformar en: detectar si hay un nodo en la lista enlazada que puede llegar a un nodo que ha sido visitado antes atravesando la lista enlazada. Por lo tanto, podemos usar dos métodos comunes para determinar si una lista enlazada tiene un anillo: el método de puntero rápido y lento y el método de tabla hash.

Tres, método de puntero rápido y lento

El método de puntero rápido y lento es un método clásico para resolver este problema, y ​​también es una de las soluciones óptimas. Se basa en dos punteros, un puntero rápido (rápido) y un puntero lento (lento), mientras se recorre la lista enlazada desde el nodo principal, el puntero rápido avanza dos pasos cada vez y el puntero lento avanza un paso cada vez. Si hay anillos en la lista enlazada, el puntero rápido eventualmente alcanzará al puntero lento y los dos se encontrarán.

Los pasos del método de puntero rápido y lento son los siguientes:

  1. Inicialice los punteros rápido y lento, ambos apuntan al nodo principal de la lista vinculada.
  2. Ingrese al bucle, la condición del bucle es que tanto el puntero rápido como el puntero lento no estén vacíos (la lista enlazada no ha terminado).
  3. En el bucle, el puntero rápido avanza dos pasos a la vez y el puntero lento avanza un paso a la vez.
  4. En cada iteración, verifique si los punteros rápido y lento se encuentran, si se encuentran, significa que la lista enlazada tiene un anillo y devuelve verdadero, de lo contrario, continúe con la siguiente iteración.
  5. Si el bucle termina, es decir, el puntero rápido o el puntero lento están vacíos, significa que la lista enlazada no tiene anillo y devuelve falso.

El siguiente es el código para implementar el método de puntero rápido y lento en Python:

class ListNode:
    def __init__(self, val=0):
        self.val = val
        self.next = None

def has_cycle(head):
    if not head or not head.next:
        return False

    slow = head
    fast = head.next

    while slow != fast:
        if not fast or not fast.next:
            return False
        slow = slow.next
        fast = fast.next.next

    return True

4. Método de tabla hash

El método de tabla hash es otra forma de resolver el problema de la lista enlazada. Aprovecha las características de la tabla hash y almacena la dirección de cada nodo en la tabla hash. En el proceso de recorrer la lista enlazada, podemos verificar si la dirección de cada nodo ha aparecido en la tabla hash y, de ser así, significa que la lista enlazada tiene un anillo.

Los pasos del método de la tabla hash son los siguientes:

  1. Inicialice una tabla hash vacía.
  2. Ingrese al bucle, la condición del bucle es que la lista enlazada no haya terminado (el nodo actual no está vacío).
  3. En el bucle, verifique si la dirección del nodo actual ha aparecido en la tabla hash, si ha aparecido, significa que la lista enlazada tiene un bucle, devuelva verdadero; de lo contrario, agregue la dirección del nodo actual a la tabla hash , y continúe atravesando el siguiente nodo.
  4. Si el bucle termina, es decir, el nodo actual está vacío, significa que la lista enlazada no tiene bucle y devuelve falso.

El siguiente es el código para implementar el método de tabla hash en Python:

def has_cycle(head):
    visited = set()

    while head:
        if head in visited:
            return True
        visited.add(head)
        head = head.next

    return False

5. Comparación y optimización

Tanto el método de puntero rápido y lento como el método de tabla hash se pueden utilizar para juzgar la lista enlazada, pero sus complejidades de tiempo y espacio son diferentes.

1. Método de puntero rápido y lento:

  • Complejidad temporal: O(n), donde n es la longitud de la lista enlazada.
  • Complejidad espacial: O(1), requiere solo un nivel constante de espacio adicional.

2. Método de tabla hash:

  • Complejidad temporal: O(n), donde n es la longitud de la lista enlazada.
  • Complejidad del espacio: O(n), necesita almacenar las direcciones de todos los nodos en la lista enlazada.

Por lo tanto, el método de puntero rápido y lento es una mejor solución, que no requiere espacio adicional y tiene una complejidad de tiempo lineal. En aplicaciones prácticas, generalmente usamos el método de puntero rápido y lento para juzgar si la lista enlazada tiene un anillo.

2023 nueva versión de estructura de datos y algoritmo Java video tutorial (Parte 1), estructura de datos y algoritmo que los programadores senior de Java deben aprender
2023 nueva versión de estructura de datos y algoritmo Java video tutorial (parte 2), estructura de datos y algoritmo que Java programador senior debe aprender

Supongo que te gusta

Origin blog.csdn.net/Itmastergo/article/details/131844957
Recomendado
Clasificación