Guía de entrevista sobre algoritmos y estructura de datos: explicación detallada del algoritmo de retroceso (1)

Algoritmo de retroceso

El "algoritmo de retroceso" es un método para resolver problemas mediante el agotamiento. Su idea central es comenzar desde un estado inicial, buscar violentamente todas las soluciones posibles y, cuando se encuentra la solución correcta, registrarla hasta encontrar una solución o hasta una No se puede encontrar la solución después de probar todas las opciones posibles.

Los algoritmos de retroceso suelen emplear una "búsqueda primero en profundidad" para recorrer el espacio de la solución. En el capítulo del árbol binario, mencionamos que el recorrido de preorden, orden y postorden son búsquedas en profundidad. A continuación, utilizamos el recorrido de preorden para construir un problema de retroceso y comprender gradualmente el principio de funcionamiento del algoritmo de retroceso.

!!! pregunta "Ejemplo de pregunta 1"

给定一个二叉树,搜索并记录所有值为 $7$ 的节点,请返回节点列表。

Para esta pregunta, recorremos el árbol en preorden y determinamos si el valor del nodo actual es 7 77 , si es así, agregue el valor del nodo a la lista de resultadosres. La implementación del proceso relevante se muestra en la siguiente figura y en el siguiente código.

=== “Python”

```python title="preorder_traversal_i_compact.py"
[class]{}-[func]{pre_order}
```

=== “C++”

```cpp title="preorder_traversal_i_compact.cpp"
[class]{}-[func]{preOrder}
```

=== “Java”

```java title="preorder_traversal_i_compact.java"
[class]{preorder_traversal_i_compact}-[func]{preOrder}
```

=== “C#”

```csharp title="preorder_traversal_i_compact.cs"
[class]{preorder_traversal_i_compact}-[func]{preOrder}
```

=== “Ir”

```go title="preorder_traversal_i_compact.go"
[class]{}-[func]{preOrderI}
```

=== “Rápido”

```swift title="preorder_traversal_i_compact.swift"
[class]{}-[func]{preOrder}
```

=== “JS”

```javascript title="preorder_traversal_i_compact.js"
[class]{}-[func]{preOrder}
```

=== “TS”

```typescript title="preorder_traversal_i_compact.ts"
[class]{}-[func]{preOrder}
```

=== “Dardo”

```dart title="preorder_traversal_i_compact.dart"
[class]{}-[func]{preOrder}
```

=== “Óxido”

```rust title="preorder_traversal_i_compact.rs"
[class]{}-[func]{pre_order}
```

=== “C”

```c title="preorder_traversal_i_compact.c"
[class]{}-[func]{preOrder}
```

=== “Zig”

```zig title="preorder_traversal_i_compact.zig"
[class]{}-[func]{preOrder}
```

Insertar descripción de la imagen aquí

Intentar y retroceder

La razón por la que se llama algoritmo de retroceso es porque el algoritmo adopta la estrategia de "intentar" y "retroceder" al buscar en el espacio de solución . Cuando el algoritmo encuentra un estado durante el proceso de búsqueda que no puede avanzar o no puede obtener una solución que satisfaga las condiciones, cancelará la elección del paso anterior, volverá al estado anterior e intentará otras opciones posibles.

En el ejemplo 1, acceder a cada nodo representa un "intento", mientras que cruzar un nodo hoja o regresar a un nodo principal returnrepresenta una "reversión".

Vale la pena señalar que el respaldo no solo incluye retornos de funciones . Para explicar esto, ampliamos ligeramente el Ejemplo 1.

!!! pregunta "Ejemplo de pregunta dos"

在二叉树中搜索所有值为 $7$ 的节点,**请返回根节点到这些节点的路径**。

Según el código del Ejemplo 1, necesitamos usar una lista pathpara registrar las rutas de los nodos visitados. Al acceder al valor 7 7Cuando el nodo sea 7 , cópielopathy agréguelo a la lista de resultadosres. Una vez completado el recorrido,restodas las soluciones se guardan en formato .

=== “Python”

```python title="preorder_traversal_ii_compact.py"
[class]{}-[func]{pre_order}
```

=== “C++”

```cpp title="preorder_traversal_ii_compact.cpp"
[class]{}-[func]{preOrder}
```

=== “Java”

```java title="preorder_traversal_ii_compact.java"
[class]{preorder_traversal_ii_compact}-[func]{preOrder}
```

=== “C#”

```csharp title="preorder_traversal_ii_compact.cs"
[class]{preorder_traversal_ii_compact}-[func]{preOrder}
```

=== “Ir”

```go title="preorder_traversal_ii_compact.go"
[class]{}-[func]{preOrderII}
```

=== “Rápido”

```swift title="preorder_traversal_ii_compact.swift"
[class]{}-[func]{preOrder}
```

=== “JS”

```javascript title="preorder_traversal_ii_compact.js"
[class]{}-[func]{preOrder}
```

=== “TS”

```typescript title="preorder_traversal_ii_compact.ts"
[class]{}-[func]{preOrder}
```

=== “Dardo”

```dart title="preorder_traversal_ii_compact.dart"
[class]{}-[func]{preOrder}
```

=== “Óxido”

```rust title="preorder_traversal_ii_compact.rs"
[class]{}-[func]{pre_order}
```

=== “C”

```c title="preorder_traversal_ii_compact.c"
[class]{}-[func]{preOrder}
```

=== “Zig”

```zig title="preorder_traversal_ii_compact.zig"
[class]{}-[func]{preOrder}
```

En cada "intento", registramos la ruta pathagregando ; antes de "revertir", necesitamos pathsacar el nodo para restaurar el estado antes de este intento .

Al observar el proceso que se muestra en la figura siguiente, podemos entender intentar y revertir como "adelante" y "deshacer" Las dos operaciones son inversas entre sí.

=== “<1>”
Insertar descripción de la imagen aquí

=== “<2>”
Insertar descripción de la imagen aquí

=== “<3>”
Insertar descripción de la imagen aquí

=== “<4>”
Insertar descripción de la imagen aquí

=== “<5>”
Insertar descripción de la imagen aquí

=== “<6>”
Insertar descripción de la imagen aquí

=== “<7>”
Insertar descripción de la imagen aquí

=== “<8>”
Insertar descripción de la imagen aquí

=== “<9>”
Insertar descripción de la imagen aquí

=== “<10>”
Insertar descripción de la imagen aquí

=== “<11>”
Insertar descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/zy_dreamer/article/details/132865295
Recomendado
Clasificación