Algoritmo de retrocesso
"Algoritmo de retrocesso" é um método de resolução de problemas por exaustão. Sua ideia central é partir de um estado inicial, buscar violentamente todas as soluções possíveis e, quando a solução correta for encontrada, registrá-la até que seja encontrada. a solução não pode ser encontrada depois de tentar todas as opções possíveis.
Algoritmos de retrocesso normalmente empregam "pesquisa em profundidade" para percorrer o espaço de solução. No capítulo sobre árvore binária, mencionamos que a travessia de pré-ordem, ordem e pós-ordem são pesquisas em profundidade. A seguir, usamos o percurso de pré-ordem para construir um problema de retrocesso e compreender gradualmente o princípio de funcionamento do algoritmo de retrocesso.
!!! pergunta "Exemplo de pergunta 1"
给定一个二叉树,搜索并记录所有值为 $7$ 的节点,请返回节点列表。
Para esta questão, percorremos a árvore em pré-ordem e determinamos se o valor do nó atual é 7 77 , em caso afirmativo, adicione o valor do nó à lista de resultadosres
. A implementação do processo relevante é mostrada na figura abaixo e no código a seguir.
=== “Píton”
```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}
```
=== “Vá”
```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}
```
=== “Ferrugem”
```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}
```
Tente reverter
A razão pela qual é chamado de algoritmo de retrocesso é que o algoritmo adota a estratégia de "tentativa" e "recuo" ao pesquisar o espaço de solução . Quando o algoritmo encontra um estado durante o processo de busca que não consegue avançar ou não consegue obter uma solução que satisfaça as condições, ele cancelará a escolha da etapa anterior, retornará ao estado anterior e tentará outras escolhas possíveis.
Para o Exemplo 1, acessar cada nó representa uma “tentativa”, enquanto cruzar um nó folha ou retornar a um nó pai return
representa uma “reversão”.
É importante notar que o fallback não inclui apenas retornos de função . Para explicar isso, expandimos ligeiramente o Exemplo 1.
!!! pergunta "Exemplo da pergunta dois"
在二叉树中搜索所有值为 $7$ 的节点,**请返回根节点到这些节点的路径**。
Com base no código do Exemplo 1, precisamos usar uma lista path
para registrar os caminhos dos nós visitados. Ao acessar o valor 7 7Quando o nó for 7 , copie-opath
e adicione-o à lista de resultadosres
. Após a conclusão do percurso,res
todas as soluções são salvas no formato .
=== “Píton”
```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}
```
=== “Vá”
```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}
```
=== “Ferrugem”
```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}
```
Em cada "tentativa", registramos o caminho path
adicionando ; antes de "reverter", precisamos path
retirar o nó para restaurar o estado antes desta tentativa .
Observando o processo mostrado na figura abaixo, podemos entender try e rollback como “forward” e “undo” .As duas operações são inversas entre si.
=== “<1>”
=== “<2>”
=== “<3>”
=== “<4>”
=== “<5>”
=== “<6>”
=== “<7>”
=== “<8>”
=== “<9>”
=== “<10>”
=== “<11>”