Revisión del algoritmo (11): volver a la lista vinculada de la estructura de datos básica

1. Escriba en el frente

Este artículo es una revisión de la lista vinculada. El funcionamiento de la lista vinculada aquí es generalmente para jugar con punteros. Los punteros dobles y los triples van de la mano. Los punteros rápidos y lentos rompen la convención. La clave para resolver el problema aquí es nada más. Primero haga un dibujo y luego busque el puntero correspondiente para realizar la operación de transformación. El lugar donde los errores son fáciles de causar está fuera de los límites, o el puntero se olvidó de moverse a un bucle infinito. Lo siguiente es ordenar algunas operaciones de rutina relacionadas con la lista vinculada, luego ordenar las preguntas y códigos específicos y, finalmente, solo ordenar las preguntas, para que pueda usarlas más tarde. Empiece a continuación. Referencia de conocimientos básicos

Acerca de la lista vinculada, necesitamos conocer los puntos de conocimiento:

  1. Operaciones comunes: agregar, eliminar, modificar y verificar elementos, las más complicadas son todo tipo de punteros

  2. Complejidad de tiempo de matriz de acceso a lista de enlaces O (n), complejidad de tiempo de inserción y eliminación O (1), la memoria no es continua

  3. Algunos de los temas más clásicos examinan la preinterpolación, la posinterpolación, el orden inverso, la inversión, la fusión y el movimiento de la lista vinculada .

  4. Algunas ideas involucradas aquí:

    • La idea del nodo principal , declarar un nodo principal, puede ser conveniente para muchas cosas. Generalmente se usa en el problema de devolver una nueva lista enlazada. Por ejemplo, dadas dos listas enlazadas ordenadas, se requiere que estén integradas y organizadas en orden. Por otro ejemplo, si los números pares e impares de una lista vinculada se separan en el orden original y luego se vuelven a combinar en una nueva lista vinculada, la primera mitad de la lista vinculada son números impares y la segunda mitad son números pares.
    • Pensamiento de inversión de cabeza
    • Recorrido de doble puntero , puede hacer muchas cosas, como intercambio por pares, orden inverso, volteo, etc.
    • La idea de punteros rápidos y lentos generalmente se puede utilizar en el ring.
    • Recurrencia, el tema de la lista enlazada es fácil de recurrir
  5. Ventajas y desventajas:

    1. Ventajas: la lista enlazada puede asignar espacio de memoria de forma flexible; puede estar en O (1) O (1)Eliminar o agregar un elemento dentro de O ( 1 ) tiempo, siempre que se conozca el elemento anterior del elemento, por supuesto, también depende de si se trata de una lista de enlace simple o una lista de enlace doble. En una lista de enlace doble , si se conoce el siguiente elemento del elemento, también puede serO (1) O (1)Elimine o agregue el elemento dentro de O ( 1 ) tiempo.
    2. Desventajas: A diferencia de la matriz, se pueden leer rápidamente los elementos de subíndice, cada vez que se lee a partir de un encabezado de una lista enlazada se lee; primera consulta kkk elementos requierenO (k) O (k)O ( k ) tiempo.
  6. Escenario de aplicación: si el problema a resolver requiere muchas consultas rápidas, es posible que la lista vinculada no sea adecuada; si el problema se encuentra, el número de elementos de datos es incierto y los datos deben agregarse y eliminarse con frecuencia, entonces el vínculo vinculado La lista será más adecuada. Y si se determina el tamaño del elemento de datos y no hay muchas operaciones de eliminación e inserción, entonces la matriz puede ser más adecuada.

  7. Sugerencia: Al resolver el problema de la lista vinculada, puede dibujar la relación entre los nodos en papel o pizarra, y luego dibujar el método de modificación, que puede ayudarlo a analizar el problema y ayudar al entrevistador a aclarar durante la entrevista. ver sus pensamientos.

Con respecto a las listas vinculadas, primero debe dominar varias rutinas: operaciones de búsqueda, inserción y eliminación.

Necesita saber cómo definir el nodo de la lista enlazada en Python. Generalmente, no necesita escribir esta parte en LeetCode, pero no la dará durante una entrevista real. Necesita escribirla usted mismo.

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

El siguiente es el funcionamiento general de la lista enlazada, tome directamente una pregunta para organizar:

  • LeetCode707: Diseñando una lista enlazada : Esta pregunta examina directamente las operaciones básicas de la lista enlazada, buscando nodos para volver al índice, insertando en la primera posición, insertando en el medio, insertando al final, borrando nodos, etc.

Este problema primero necesita establecer un nodo de lista vinculado, el código anterior, y luego inicializar un nodo principal

class MyLinkedList:
    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.dummyHead = ListNode(-1)

La operación de búsqueda de la lista vinculada, dado el índice, devuelve el valor del índice correspondiente

def get(self, index: int) -> int:
    """
    Get the value of the index-th node in the linked list. If the index is invalid, return -1.
    """
    if index < 0: return -1
    p = self.dummyHead.next
    cou = 0
    while p and cou < index:
        p = p.next
        cou += 1
    # self.printl()   打印当前链表结果
    return p.val if p else -1

Insertar en la primera posición de la lista vinculada:

def addAtHead(self, val: int) -> None:
    """
    Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list.
    """
    node = ListNode(val)
    node.next = self.dummyHead.next
    self.dummyHead.next = node
    # self.printl()   # 打印当前链表结果

Insertar al final de la lista vinculada:

def addAtTail(self, val: int) -> None:
    """
    Append a node of value val to the last element of the linked list.
    """
    node = ListNode(val)
    # 首先到尾部
    pre, cur = self.dummyHead, self.dummyHead.next
    while cur:
        pre, cur = cur, cur.next
    pre.next = node
    # self.printl()   # 打印当前链表结果

Insertar en la posición especificada de la lista vinculada:

def addAtIndex(self, index: int, val: int) -> None:
    """
    Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted.
    """
    node = ListNode(val)
    cou = 0
    pre, cur = self.dummyHead, self.dummyHead.next
    while cur and cou < index:
        pre, cur = cur, cur.next
        cou += 1
    # 插入
    node.next = cur
    pre.next = node
    # self.printl()   打印当前链表结果

Eliminar operación de lista vinculada:

def deleteAtIndex(self, index: int) -> None:
    """
    Delete the index-th node in the linked list, if the index is valid.
    """
    cou = 0
    pre, cur = self.dummyHead, self.dummyHead.next
    while cur and cou < index:
        pre, cur = cur, cur.next
        cou += 1
    # 删除
    pre.next = cur.next if cur else None
    # self.printl()   打印当前链表结果

Para la depuración, también escribí una función para generar los elementos de la lista vinculada, porque cuando la envié por primera vez, había un error y no sé qué paso era el problema, así que escribí una función como esto, después de cada paso de la operación, imprímalo y el error aparece instantáneamente.

def printl(self):
    p = self.dummyHead.next
    while p:
        print(p.val, end=',')
        p = p.next
    print()

En cuanto al código básico, existen dos operaciones más, la inserción hacia adelante y la inserción final para construir una lista enlazada, que se cumplirán en la comprensión de temas específicos. La interpolación frontal obtendrá una lista enlazada invertida, y la interpolación de cola obtendrá una lista enlazada normal.

Mire el tema específico a continuación.

2. Cuestionar ideas y ordenar códigos

2.1 Eliminación de elementos de lista vinculados

  • LeetCode203: Eliminar elementos de listas vinculadas : El problema más básico de las operaciones de listas vinculadas, examinar la eliminación de listas vinculadas. En este momento, los dos punteros pre y cur están atravesados. Pre es responsable de apuntar al nodo anterior de cur, y es responsable de eliminar elementos después de encontrarlos, y cur es responsable de encontrar el elemento de destino. Declarar el nodo principal facilitará la operación.
    Inserte la descripción de la imagen aquí
  • LeetCode19: Eliminar el nodo K de la lista vinculada : esto necesita usar los punterosfast, slowfast rápido y lento , suelte n pasos primero, luego rápido y lento van de la mano, cuando fastllega al final, slowes el nodo n del bottom , pero aquí queremos eliminar el n-ésimo nodo del Nodo inferior , por lo que mientras avanza, debe haber un nodo frente al registro lento. Para unificar la eliminación del primero y el del medio, aquí se necesita un nodo principal.
    Inserte la descripción de la imagen aquí

2.2 Reversión de la lista enlazada

  • LeetCode206: Lista enlazada inversa : hay tres formas de hacer esto, y todas son muy básicas, quiero ordenarlas aquí.

    1. En primer lugar, pre, curestos dos amigos son realmente fáciles de usar. Cuando se desplaza hacia adelante, el puntero se ajusta por cierto. El código para el ajuste del puntero en Python puede usar el desempaquetado de tuplas para ser más conciso, pero antes de escribir esto, es mejor Escribe el prototipo, de lo contrario es fácil cometer errores:
      Inserte la descripción de la imagen aquí
      de hecho , es muy sencillo escribir el código anterior de acuerdo con el prototipo. El lado izquierdo del signo igual en el prototipo se coloca a la izquierda en orden, y el derecho El lado del signo igual en el prototipo se coloca a la derecha en orden. Pero el prototipo debe estar escrito correctamente, esto está relacionado con el orden de manipulación.
    2. La idea de reconstruir la matriz con la interpolación de la cabeza: como se mencionó anteriormente, la interpolación de la cabeza puede crear una lista vinculada en orden inverso.
      Inserte la descripción de la imagen aquí
    3. Pensamiento recursivo: esta pregunta puede ser recursiva de cola. Para el nodo entrante actual, si obtengo el orden inverso de los nodos detrás de él, es decir, si tengo head->nexttodo el orden inverso, solo necesito conectar la cabeza al final "Solo acéptalo. Basado en esta idea, se puede usar la recursividad de cola."

      Inserte la descripción de la imagen aquí
  • LeetCode25: K un grupo de listas enlazadas invertidas : esta pregunta necesita usar la idea de invertir listas enlazadas, pero aquí no se trata de revertir todas, sino de revertir un grupo, así que primero escriba la inversión de lista enlazada anterior como una función para darse cuenta de la inversión de [a, b)Node. Entonces se puede revertir, y aquí está la idea de reconstruir la lista enlazada insertando K nodos al final a la vez. Use dos punteros k_start, k_end, k_endvaya kk primeroPaso k , y luego invierta[k_start, k_end)el nodo, inserte la cola del nodo invertido en la nueva lista vinculada (la forma de inserción de la cola). Luego continúe realizando el proceso anterior, cuando se encuentre que este último no es suficientekkSi hay k , inserte las colas directas restantes en la nueva lista vinculada. La clave aquí es invertir el nodo de la lista de enlaces y la idea de inserción de la cola en una posición determinada.
    Inserte la descripción de la imagen aquí

  • LeetCode61: Lista enlazada rotativa : he jugado con matrices rotativas antes. Aquí está la selección de listas enlazadas. La idea es en realidad la misma que la de matrices. Primero, invierta el orden general, luego invierta la primera k, y luego invierta la k después de eso. En ese momento, el funcionamiento de la lista enlazada no podría ser tan sencillo. Cuando se invierte el orden, la función inversa anterior es muy importante. Sigue siendo la idea de interpolación de cola + operación de nodo de intervalo inverso
    Inserte la descripción de la imagen aquí

2.3 Intercambio de nodos de listas vinculadas

  • Intercambiar los nodos en la lista vinculada en pares : este tema es el intercambio nuevamente, y el intercambio es similar al orden inverso, pero esto es más simple, es el orden inverso de los nodos adyacentes, la idea de doble puntero + inserción de cola para crear una lista vinculada .
    Inserte la descripción de la imagen aquí

2.4 Lista circular enlazada

  • Lista enlazada circular : La mejor herramienta para encontrar el anillo en la lista enlazada es el puntero de velocidad. Define dos punteros fast, slow. Cada vez que slowbajas un paso fasty dos pasos hacia abajo. Si se encuentran en un momento determinado, significa que hay anillo.

    Inserte la descripción de la imagen aquí
  • Lista circular enlazada II : Esta pregunta está directamente sobre la idea. Para encontrar la entrada del anillo, primero busque el punto de encuentro. Después de eso, regresa lentamente al punto de partida y estancias rápidas en el punto de encuentro. Los dos avanzan paso a paso. Paso. Cuando se reencuentren, es la entrada del ring. ¿Por qué? Al principio, este es un problema de cálculo de la distancia. Suponiendo que cuando el primer encuentro, lento da K pasos, luego rápido da 2K pasos (la velocidad es el doble de lenta), entonces es equivalente a caminar lento desde el punto de partida hasta el encuentro La distancia del punto es igual a la distancia de ayuno desde el punto de encuentro, girando un círculo de regreso al punto de encuentro , y el punto de partida no es más que antes del punto de encuentro. Por ejemplo, si da un paso atrás desde el punto de encuentro punto de encuentro al punto de partida, luego la cabecera se aleja del punto de partida, es lo mismo que la distancia del punto de encuentro al punto de partida, que son Km escalones. Entonces, los dos se encuentran primero, luego regresan lentamente al punto de partida, y luego caminan sincrónicamente, y luego se encuentran es el punto de partida.

Inserte la descripción de la imagen aquí

Por supuesto, los dos bucles que se encuentran arriba también se pueden eliminar fácilmente con una tabla hash. Tome la segunda entrada de búsqueda de bucles, solo se necesita un puntero para atravesar la lista vinculada. Cada vez que se atraviesa un nodo, se guardará. En la colección del set. Cuando se encuentra que se ha atravesado cierto nodo, ya existe este nodo en la tabla hash, lo que indica que esta es la entrada del anillo, simplemente regrese a este nodo. De manera similar, también se puede juzgar que hay un anillo en este momento.
Inserte la descripción de la imagen aquí

  • LeetCode876: El nodo medio de la lista vinculada : el problema clásico de los punteros rápidos y lentos. Ambos comienzan desde el principio al mismo tiempo. Rápido toma dos pasos a la vez y lento toma un paso a la vez, pero cuando rápido va a al final, lento es el nodo del medio en este momento.
    Inserte la descripción de la imagen aquí

2.5 Fusión de listas vinculadas

3. Sr. General

Hay relativamente pocas preguntas en la lista vinculada, así que me tomé un día para revisarla nuevamente. Algunas ideas básicas son muy importantes, y el dibujo también es muy importante. Aquí está la configuración estándar que suelo usar en la lista vinculada:

  1. Nodo principaldummyHead
  2. pre, curDos punteros
  3. fast, slowDos punteros
  4. Tapón de cola + doble puntero, tapón de cola + tapón de cabeza

Ahora la configuración estándar de punteros dobles:
5. pre, curDos punteros (punteros hacia adelante y hacia atrás -> inserción, eliminación e inversión de nodos de lista enlazados)
6. fast, slowDos punteros (puntero rápido y lento -> juzgando el anillo, encuentre el punto medio del lista enlazada, busque el N del nodo inferior)
7. left, rightDos punteros (punteros izquierdo y derecho -> matriz, temas relacionados con cadenas)
8. win_start, win_endDos punteros (ventana deslizante -> submatriz, temas relacionados con subcadenas)

Pensamientos importantes en esta pieza:

  • Tapón de cola + puntero doble
  • Nodo de lista enlazada de intervalo inverso + inserción de cola
  • Tapón de cola + tapón de cabeza

El tema final se resume de la siguiente manera:

Eliminación de elementos de lista vinculados:

Reversión de lista enlazada

Intercambio de nodos de listas vinculadas

Lista enlazada circular

Fusión de lista vinculada

Supongo que te gusta

Origin blog.csdn.net/wuzhongqiang/article/details/115266111
Recomendado
Clasificación