代码随想录算法训练营第二十五天|216.组合总和III、17.电话号码的字母组合
216.组合总和III
问题简述:在1~9中找出个数为k的和为n的所有组合。
思考:和上一次的回溯很像很像。
算法思路:定义一个startIndex作为每次循环的起始位置,path为每个结果的路径,sum为当前路径的总和。进行操作时首先判断当前的sum是否大于n,如果大于n直接返回并回溯,然后判断当path元素个数为k且总和为n时,将path加入lists并返回。在path中加入元素,sum中加入当前元素,再进行递归,递归的startIndex加1即为加入当前元素后面的元素,保证path中不再重复。递归完成后再移除上一步加入的元素,并将sum剪去当前元素值。同时在进行for循环时考虑到剪枝,i最大只能为9 - (k - path.size()) + 1
,当大于这个数时,结果不再成立。
import java.util.ArrayList;
import java.util.List;
class Solution {
List<List<Integer>> lists = new ArrayList<>();
List<Integer> path = new ArrayList<>();
int sum = 0;
public List<List<Integer>> combinationSum3(int k, int n) {
backtracking(n, k, 1);
return lists;
}
public void backtracking(int n,int k,int startIndex){
//剪枝叶
if (sum > n){
return;
}
//确定终止条件
if (path.size() == k && sum == n){
//这里注意需要新创建一个ArrayList将path的值放入lists,不可以直接将path放入
lists.add(new ArrayList<>(path));
return;
}
//进行循环并回溯,同时进行剪枝
for (int i = startIndex; i <= 9 - (k - path.size()) + 1; i++) {
path.add(i);
sum += i;
backtracking(n, k, i + 1);
//回溯
sum -= i;
path.remove(path.size() - 1);
}
}
}
17.电话号码的字母组合
问题简述:将给定的digits中所有的数字对应的字母任取一个组合成长度为digits长度的字符串,将左右的结果返回。
思考:这个题涉及到的将字符转换为数字的方法需要注意,直接-'0'
将字符数字变为数字。然后将数字对应成字母的方法也要记住,之前一直在想用某个函数对应一下数字和字母,其实是一个等差数列,但是因为有的数字对应了四个字母所以不行。
算法思路:定义一个startIndex作为每次递归中digits的位置,s存储每个结果,list存储s的集合。将所有的字母存入字符串数组numString。如果digits为空,返回空list;如果s的长度等于digits的长度,则将s加入list。如果不等于,则循环当前数字对应的字母个数次,每次将当前数字对应字母加入s,再进行递归下一个数字,最好删除当前字母进行回溯。
import java.util.ArrayList;
import java.util.List;
class Solution {
//用来存最终结果
List<String> list = new ArrayList<>();
//用来存list中的每个字符串
StringBuilder s = new StringBuilder();
//用来寻找对应字符
String[] numString = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
public List<String> letterCombinations(String digits) {
if (digits == null || digits.length() == 0) {
return list;
}
//最初的其实位置为0
backtracking(digits, 0);
return list;
}
public void backtracking(String digits, int startIndex){
//如果长度够了,则加入进list
if (s.length() == digits.length()){
list.add(new String(s));
return;
}
//循环的次数为当前字符对应字母的个数,-'0'将字符变为数字
int length = numString[digits.charAt(startIndex) - '0'].length();
for (int j = 0; j < length; j++) {
//加入当前digits的i位置对应的字母
s.append(numString[digits.charAt(startIndex) - '0'].charAt(j));
//递归加入字母
backtracking(digits,startIndex + 1);
//进行回溯
s.deleteCharAt(s.length() - 1);
}
}
}
感想
我感觉我心里就默认了旅游是对自己努力的奖励,看电视剧是自己浪费时间的证据。