Problèmes qui peuvent généralement être résolus par l’algorithme de backtracking :
- Problèmes de combinaison : tels que LeetCode-77-combination , LeetCode-39-combination sum , LeetCode-40-combination sum II , LeetCode-216-combination sum II , LeetCode-17-letter combinaison de numéro de téléphone
- Problème de segmentation : tel que la chaîne palindrome divisée LeetCode-131 , l'adresse IP LeetCode-93-restauration
- Problème de sous-ensemble : tel que LeetCode-78-subset , LeetCode-90-subset II , LeetCode-491-sous-séquence croissante
- Problèmes d'arrangement : tels que LeetCode-46-Full Arrangement , LeetCode-46-Full Arrangement II
- Problèmes d'échiquier : tels que LeetCode-51-N Queen , LeetCode-37-Solution Reading
Trilogie récursive :
① Déterminer les paramètres et la valeur de retour de la fonction récursive ; généralement nul, et le nom est généralement un retour en arrière
② Déterminer la condition de terminaison ;
③ Déterminer la logique récursive monocouche.
Idées de résolution de problèmes combinées LeetCode-77 :
- La détermination des paramètres de la fonction récursive nécessite n, k et un indice changeant startIndex
- Déterminez la condition de terminaison. C'est simple. Lorsque la longueur du tableau unidimensionnel est égale à k, cela signifie que c'est suffisant et arrêtez-vous ;
- Pour déterminer la logique récursive monocouche, vous devez déterminer par où commencer le jugement. La question commence à partir de 1, donc l'indice commence également à partir de 1 et commence à revenir en arrière dans la boucle for, maisAfin d'ajouter facilement l'élément suivant après chaque trace, c'est-à-dire de revenir au nœud parent de la structure arborescente, nous devons faire apparaître un élément, c'est facile à ignorer.
Code
class Solution {
/**
* @param n 1~n
* @param k 要求的个数
* @return 返回范围 [1, n] 中所有可能的 k 个数的组合
*/
public List<List<Integer>> combine(int n, int k) {
backtracking(n,k,1);
return res;
}
List<List<Integer>> res = new ArrayList<>();//二维数组,要返回的结果
List<Integer> path = new ArrayList<>();// 树形结构走的路径,即能放进去的数
public void backtracking(int n, int k, int startIndex){
if (path.size() == k){
// 终止条件
res.add(new ArrayList<>(path));// 满足条件,将一维数组加到结果集中
return;// 切记需要返回
}
for (int i = startIndex; i <= n; i++) {
// 没有剪枝的情况
path.add(i);
backtracking(n,k,i+1);// 回溯
path.remove(path.size()-1);// 还需要弹出一个元素,即表示回到上一步
}
}
}