Problemas de algoritmo de listas vinculadas a habilidades de programación recursiva de Leetcode

 Hoy principalmente quiero compartir 2 pequeños consejos:

  1. Una comprensión de la analogía de punteros rápidos y lentos

  2. Hablar sobre técnicas de programación recursiva y cómo las entiendo y uso yo mismo.

Pregunta de apertura 1: leetcode 141: lista enlazada circular

Descripción del Título:

  Dada una lista vinculada, determine si hay un anillo en la lista vinculada.
  Si hay un nodo en la lista vinculada al que se puede acceder de nuevo mediante el seguimiento continuo del siguiente puntero, hay un anillo en la lista vinculada. Para representar los anillos en una lista vinculada dada, usamos el entero pos para indicar la posición donde el final de la lista vinculada está conectado a la lista vinculada (el índice comienza desde 0). Si pos es -1, entonces no hay ningún anillo en la lista vinculada. Nota: pos no se pasa como parámetro , solo para identificar la situación real de la lista enlazada.
  Si hay un anillo en la lista vinculada, devuelve verdadero. De lo contrario, devuelve falso.

Ejemplo:

Ideas de resolución de problemas:

  La idea de punteros de velocidad prácticos.
  Analogía: Por ejemplo, en el patio de recreo de la escuela, A y B corren alrededor del patio de recreo. A corre despacio y B corre rápido. Después de que comienzan a correr, con el tiempo, eventualmente se encontrarán en un lugar determinado del patio de recreo. 
  Si A y B corren por una carretera, uno más lento y el otro rápido, nunca tendrán la oportunidad de encontrarse.
  Los indicadores rápidos y lentos utilizan los principios anteriores, los indicadores lentos van un paso a la vez, los indicadores rápidos van de dos pasos a la vez. Recorra toda la lista vinculada de esta manera. Si no se encuentran, no hay anillo, como una autopista. Si se encuentran, significa que hay un bucle, como una pista circular en el patio de una escuela.

 

Implementación de codificación

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     public var val: Int
 *     public var next: ListNode?
 *     public init(_ val: Int) {
 *         self.val = val
 *         self.next = nil
 *     }
 * }
 */
class Solution: NSObject {
    func hasCycle(_ head: ListNode?) -> Bool {
        if head == nil || head?.next == nil { return false }
        var slow = head
        var fast = head?.next
        while fast != nil && fast?.next != nil {
            if slow === fast { return true }
            slow = slow?.next
            fast = fast?.next?.next
        }
        return false
    }
}

Pregunta 2: Leetcode 141: lista enlazada inversa

Descripción del Título:

  Invierta una lista enlazada individualmente.

 

Ejemplo:

输入: 5->4->3->2->1->NULL
输出: 1->2->3->4->5->NULL

 

Recurrencia:

  Déjame darte un ejemplo: [No original]
  Los fines de semana llevabas a tu novia al cine a ver una película. La novia te preguntaba, ¿en qué fila estamos sentados ahora? El cine está demasiado oscuro para ver con claridad o contar. ¿Qué haces ahora?

  No olvides que eres un programador. Esto no puede preocuparte. La recursividad empezará a ser útil. Entonces le pregunta a la persona en la primera fila en qué fila está. Solo necesita agregar uno a su número para saber en qué fila se encuentra. Sin embargo, las personas que estaban al frente no podían ver con claridad, por lo que también preguntó a las personas que estaban frente a él. Simplemente avance en una fila como esta, hasta que le pregunte a la persona en la primera fila que estoy en la primera fila, y luego vuelva a pasar los números en una fila tras otra. Hasta que la persona que está frente a ti te diga en qué fila se encuentra, sabrás la respuesta. Este es un proceso de descomposición muy estándar de resolución de problemas recursiva. El proceso de ir se llama "pasar" y el proceso de regresar se llama "recursivo " . Básicamente, todos los problemas recursivos se pueden expresar mediante fórmulas recursivas. Solo este ejemplo en la vida ", usamos la fórmula recursiva para expresarlo así:

f(n)=f(n-1)+1 其中,f(1)=1

  f (n) significa que quieres saber en qué fila estás, f (n-1) significa el número de filas en la fila anterior, f (1) = 1 significa que la persona en la primera fila sabe que estás en la primera fila. Con esta fórmula recursiva, podemos cambiarla fácilmente a código recursivo, de la siguiente manera:

int f(int n) {
  if (n == 1) return 1;
  return f(n-1) + 1;
}

  A través de los ejemplos anteriores, todos deberían tener una comprensión más clara de la recursividad. Entonces, en el desarrollo real, ¿cómo se ejecuta el código en recursividad? Veamos el siguiente código:

   func test(index: Int) -> Int{
        if index == 0 { return 0}
        print("-------\(index)") //第一行打印,记为A
        let result = test(index: index-1)
        print("=======\(index)") //第一行打印,记B
        return result
    }
text(index:2)

  [Pregunta: ¿Cuál es el orden de impresión de A y B en el interior?

打印结果:
-------2
-------1
=======1
=======2

  ¿Cómo lo entiendes?  Reescribí el código para que puedas entender

    func test(index: 2){
        print(-------2)
        let result = {
            func test(1){
                print(-------1)
                let result = test(0)
                print(=====0)
            }
        }
        print(======2)
        return result
    }

 

Pensamiento recursivo

  1. El método f en el ejemplo de la sala de cine se usa para encontrar en qué fila se encuentra la posición actual -> conocer la función del método f

  2. La fórmula de implementación esf(n)=f(n-1)+1 其中,f(1)=1

  3. Déjalo ir y déjalo correr por sí mismo

     

Responde la pregunta 2

1. La función reverseList se utiliza para invertir la lista vinculada
2. Fórmula de implementación:

newHead = reverseList(head.next)
head.next.next = head
head = nil

3. Recurrir

Implementación de codificación

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     public var val: Int
 *     public var next: ListNode?
 *     public init(_ val: Int) {
 *         self.val = val
 *         self.next = nil
 *     }
 * }
 */

class Solution {
  func reverseList(_ head: ListNode?) -> ListNode? {
        if head == nil || head?.next == nil { return head }
        let newHead = reverseList(head?.next)
        head?.next?.next = head
        head?.next = nil
        return newHead
    }
}

¿Cómo entenderlo simple y correctamente?

  Anotemos el código juntos y sigamos el flujo del código nuevamente.

  1. Entramos5->4->3->2->1->NULL

  2. head = 5 no está vacío, y luego ejecuta reverseList (head? .next) que es reverseList (4)

  3. En el paso 2, el resultado final de reverseList (4) es 1->2->3->4->NULL[porque la función de reverseList es invertir]

  4. head.next.next = head, es decir, head.next.next = 5

  5. Finalmente cabeza = nulo

  6. done
    necesita tratar reverseList (head) como un todo. De hecho, el programa también se ejecuta así.

     

para resumir

  Hoy entendemos el principio de punteros rápidos y lentos, a través de la analogía podemos entenderlo bien y recordar su principio durante mucho tiempo. Luego analizamos la idea de recursividad y la pila de llamadas dentro de la recursividad. Finalmente, nos dimos cuenta de la solución del problema del algoritmo de lista enlazada a través de la codificación. Al final del artículo, lo que quiero decir es que la recursividad es realmente difícil de entender. Si realmente quieres dominarlo, como yo, escribe una función de prueba (intdx: int) para probarlo, pasa por el recursivo proceso, sabe que sabe cómo volver, y se sorprenderá si lo hace usted mismo.

Bienvenido a prestar atención a la cuenta pública de [The Way of Infinite Testing], responder a [recibir recursos],
recursos de aprendizaje de programación de Python productos secos, automatización de la interfaz de usuario de la aplicación del marco Python + Appium , automatización de la interfaz de usuario web del marco Python + Selenium, API del marco Python + Unittest automatización,


Los recursos y códigos se envían gratis ~
Hay un código QR de la cuenta oficial en la parte inferior del artículo, puede escanearlo en WeChat y seguirlo.

Observaciones: Mi cuenta pública personal se ha abierto oficialmente, dedicada al intercambio de tecnología de prueba, que incluye: pruebas de big data, pruebas funcionales, desarrollo de pruebas, automatización de la interfaz API, operación y mantenimiento de pruebas, pruebas de automatización de la interfaz de usuario, etc., búsqueda pública de WeChat cuenta: "Wuliang The Way of Testing", o escanee el código QR a continuación:

 ¡Presta atención y crezcamos juntos!

 

 

 

Supongo que te gusta

Origin blog.csdn.net/weixin_41754309/article/details/109560614
Recomendado
Clasificación