一般にバックトラッキング アルゴリズムで解決できる問題:
- 組み合わせ問題: LeetCode-77-combination、LeetCode-39-combination sum、LeetCode-40-combination sum II、LeetCode-216-combination sum II、LeetCode-17- 電話番号の文字の組み合わせなど
- セグメンテーションの問題: LeetCode-131-分割回文文字列、LeetCode-93-IP アドレスの復元など
- サブセット問題: LeetCode-78-subset、LeetCode-90-subset II、LeetCode-491-increeasing subsequenceなど
- 編曲問題: LeetCode-46-Full Arrangement、LeetCode-46-Full Arrangement IIなど
- チェス盤の問題: LeetCode-51-N Queen、LeetCode-37-Solution Readingなど
再帰三部作:
① 再帰関数のパラメータと戻り値を決定します。通常は void、名前は通常 backtracking です。
② 終了条件を決定します。
③ 単層再帰ロジックを決定します。
LeetCode-77 の組み合わせによる問題解決のアイデア:
- 再帰関数のパラメータを決定するには、n、k、および変更される添字 startIndex が必要です
- 終了条件を決める これは簡単で、1次元配列の長さがkに等しい場合は、それで十分なので停止するだけです。
- 単層再帰ロジックを決定するには、どこから判断するかを考える必要があり、質問が1から始まるので添字も1から始まり、forループ内で遡行を開始しますが、各バックトレースの後に次の要素を簡単に追加するには、つまりツリー構造の親ノードに戻るには、要素をポップアップする必要があります。、これは無視するのが簡単です。
コード
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);// 还需要弹出一个元素,即表示回到上一步
}
}
}