目次
216. 合算額Ⅲ
組み合わせ問題を理解していれば、この問題は簡単になります。
トピックリンク/記事説明: code caprice
動画解説:組み合わせ問題とどう違うの?バックトラッキング アルゴリズムはどのように枝刈りを行うのでしょうか? | LeetCode: 216. 合計値 III_哔哩哔哩_bilibili
解決策のアイデア:
この質問は質問 77 に似ていますが、主にバックトラッキング アルゴリズムのテンプレート作成方法に精通しているため、この質問には 2 つの枝刈りの状況があり、検索時間を短縮できます。具体的な枝刈り操作は次のとおりです (詳細コード内のメモ): 紙切り操作
1 : 追加された要素の合計がターゲットの合計より大きい場合、この再帰を終了するのに間に合うように戻り、次の再帰操作に進みます。枝刈り操作 2、制御が終了した
ときk 個の数値に到達する必要があり、最大で終了する場所までトラバースする必要があります。具体的な操作は9 - (k - path.size()) + 1です。!!
class Solution {
LinkedList<Integer> path = new LinkedList<>();
List<List<Integer>> result = new ArrayList<>();
int sum = 0;
public List<List<Integer>> combinationSum3(int k, int n) {
backtracking(k,n,1);
return result;
}
public void backtracking(int k, int n, int startIndex){
if(sum > n) return ; //剪纸操作一:如果添加的元素和大于目标之和时,及时return结束本次递归,进行下一次递归操作即可
if(path.size() == k ){
if(sum == n){
result.add(new LinkedList(path));
return;
}
}
for(int i = startIndex; i <= 9 - (k - path.size()) + 1; i++ ){ //9 - (k - path.size()) + 1:这里是剪枝操作二,控制要达到k个个数时,最多还需要遍历到哪里结束即可
path.add(i); //往path路径中及时添加元素
sum += i; //添加的元素及时相加操作
backtracking(k, n, i + 1); //不断的朝着深度方向进行搜索,直到遇到return结束方法的语句才算完成一次递归,紧接着进行回溯操作
path.removeLast(); //递归遇到return后及时减去刚添加的元素,回溯到第一次递归的状态
sum -= i; //递归遇到return后及时减去刚添加的元素,回溯到前一次递归的状态
}
}
}
17. 電話番号のアルファベットの組み合わせ
最初は誰でも少し難しい問題だと思いますが、まずは20分くらい自分で考えて、分からなければ答えを見てください。
トピックリンク/記事説明: code caprice
ビデオの説明:バックトラッキング アルゴリズムを使用する必要があります。| LeetCode: 17. 電話番号の文字の組み合わせ_哔哩哔哩_bilibili
解決策のアイデア:
この質問は依然として Ka Ge によって導かれる必要があります。そうでないと、このような包括的な解決策を考えるのはそれほど簡単ではありません。主に最初のステップです。まず、配列添字を介して数値キーボードを文字列にマップし、次に文字の組み合わせを取得します。文字列に, 次に、段階的な分析のために対応するツリー構造を描画します。初めてこの質問を書いたとき、どこから始めればよいのかわかりませんでした。質問を見たとき、私は直接混乱しました。内部の関係はツリー状のソリューションに従っています。問題ありません。
class Solution {
String[] mapLetter = {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"}; //第一步:先把数字键盘通过数组下标映射成字符串,然后取字符串里面的字母组合
LinkedList<String> path = new LinkedList<>();
List<String> result = new ArrayList<>();
StringBuilder temp = new StringBuilder(); //大量的字符串拼接可以选择更为高效的StringBuilder
public List<String> letterCombinations(String digits) {
if(digits == null || digits.length() == 0) return result; //这个剪枝操作是真恶心,还是需要直接判断如果digits == [""]或者不存在时时,直接return结果集即可
bancktracking(digits,0);
return result;
}
public void bancktracking(String digits, int index){ //index变量指向的是给定的数字字符串中的下标索引值,由于结果集中的大小和数字字符串大小一致,所以可以用过索引值控制回溯算法的终止条件,如下所示
if(index == digits.length()){ //index从0开始索引给定的数字字符,通过index的索引值控制递归的终止条件,只有当满足终止条件时,才进行结果的处理
result.add(temp.toString());
return;
}
String letter = mapLetter[digits.charAt(index) - '0']; //digits[index]:获取给定数字字符串指定索引值的数字字符,从0开始获取的;digits[index] - '0':获取对应数字字符的int的数,传入到映射数组中,再获取数字字符对应的字符串!!!
//这里要注意踩坑,一定是digits[index] - '0':表示两个字符串进行相加操作,得到的是int类型结果,'2'- '0' == 2,而不是digits[index] - 0:表示吧'2'先转换成ASCII码,其数值为50,再与0进行相减操作;
for(int i = 0; i < letter.length(); i++){
temp.append(letter.charAt(i));
bancktracking(digits, index + 1);
temp.deleteCharAt(temp.length() - 1);
}
}
}