1. Problemas que puede resolver el método de búsqueda con retroceso
(1) Problema de combinación : por ejemplo, hay varias combinaciones de longitud 2 en 1, 2, 3, 4, 12, 13, 14, 23 , 24, 34. No se requiere orden
(2) Problema de corte : después de hablar sobre cortar una cuerda, asegúrese de que las subcadenas cortadas sean todas palíndromas.
(3) Problema de subconjunto : por ejemplo, todos los subconjuntos en 1, 2, 3, 4. No se requiere orden
(4) Problema de disposición : por ejemplo, varias combinaciones de longitud 2 en 1, 2, 3, 4 son 12, 13, 14, 23 , 24, 34, 31, 21, 41, 32, 42 , 43. Necesita orden.
(4) Problema de tablero de ajedrez : problema de n reina
Es difícil resolver los problemas mencionados anteriormente utilizando bucles, por lo que los problemas mencionados anteriormente deben resolverse mediante el método de retroceso.
2. La idea del método de búsqueda con retroceso
El retroceso se puede abstraer como una estructura de árbol, y el retroceso se puede entender como un bucle for de ancho horizontal y recursividad de profundidad vertical de un árbol.
3. La rutina general de escribir código (plantilla)
public void backtracking () // define la función de retroceso
{
// 1, condiciones de rescisión
if (condición de terminación)
{
Recoger resultados;
regreso ;
}
// 2, para el nodo de procesamiento de ejecución del bucle, función recursiva, función de retroceso
para (atravesando elementos de colección)
{
Nodo de procesamiento
función recursiva
Función de retroceso
}
devuelve el resultado final del recorrido.
}
4. Aplicación del problema de combinación de algoritmo de retroceso
Primero haga la pregunta, saque todos los conjuntos de longitud 2 en 1, 2, 3 y 4
el código se muestra a continuación:
para (int i = 0 ; i <núm. de longitud; i ++)
{
para (int j = i; j <longitud num.; j ++)
{
System.out.print (i) ;
System.out.print (j) ;
}
}
Pero si cambiamos la matriz anterior a una combinación de 100 números y una longitud de 50, se necesitan 50 niveles de bucles for para anidar, lo que obviamente no es realista.
En este momento necesitamos realizar un algoritmo de retroceso
Explique esta figura, por qué cada vez que toma un valor, las siguientes ramas no tienen este número, porque la definición de combinación es que la combinación no está en orden, por lo que si no habla de la pérdida de la matriz frontal, inevitablemente hará que los datos se repitan.
Código
Valor de retorno del parámetro de función recursiva
Determinar las condiciones de terminación
Función recursiva de un solo nivel
Código fuente:
List<List<Integer>> result = new ArrayList<List<Integer>>();
List<Integer> path= new ArrayList<Integer>();
List<Integer> path2;
public List<List<Integer>> combine(int n, int k)
{
backstracking(n,k,1);
return result;
}
public void backstracking(int n,int k,int startindex)
{
if(path.size()==k)
{
path2=new ArrayList<Integer>();
for (int i: path)
{
path2.add(i);
}
result.add(path2);
return ;
}
for(int i=startindex;i<=n;i++)
{
path.add(i);
backstracking(n,k,i+1);//这里为什么是i+1呢因为不能出现两个字母的重复,如果是i的话就会出现11,22,33这种情况。
path.remove(path.size()-1);
}
}
5. Aplicación del problema de la poda del algoritmo de retroceso del problema de combinación
Como se muestra en la siguiente figura: si n = 4 y k = 4, una búsqueda puramente violenta será un gran desperdicio de recursos informáticos, por lo que este algoritmo debe optimizarse para reducir la complejidad de tiempo de este algoritmo.
Lo principal a cambiar es que el tamaño se cambia a n- (k-path.size) +1;
6. Aplicación de la suma combinada del algoritmo de retroceso
Escenas:
Dada una matriz de candidatos sin elementos repetidos y un objetivo de número objetivo, busque todas las combinaciones de candidatos que pueden hacer el objetivo de suma de números.
El número de candidatos se puede seleccionar repetidamente sin limitación.
Descripción:
Todos los números (incluido el objetivo) son números enteros positivos.
El conjunto de soluciones no puede contener combinaciones repetidas.
Ideas:
Ideas de escritura de código
Valor de retorno del parámetro de función recursiva
Determinar las condiciones de terminación
Función recursiva de un solo nivel
Código fuente:
import java.util.*;
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target)
{
int sum=0;
int startindex=0;
backtracking(candidates,target,sum,startindex);
return result;
}
List<List<Integer>> result=new ArrayList<List<Integer>>();
List<Integer> path =new ArrayList<Integer>();
List<Integer> path2;
public void backtracking(int[] candidates, int target,int sum,int startindex)
{
//首先确定函数的参数以及返回值
if(sum>target)
{
return ;
}
//确定终止条件
if(sum==target)
{
path2=new ArrayList<Integer>();
for(int i: path)
{
path2.add(i);
}
result.add(path2);
return;
}
//确定单层递归函数
for(int i=startindex;i<candidates.length;i++)
{
path.add(candidates[i]);
sum=sum+candidates[i];
backtracking(candidates,target,sum,i);
sum=sum-candidates[i];
path.remove(path.size()-1);
}
return ;
}
}