语言:Java/Go
216.组合总和III
找出所有相加之和为 n 的 k 个数的组合。组合中只允许含有 1 - 9 的正整数,并且每种组合中不存在重复的数字。
说明:
- 所有数字都是正整数。
- 解集不能包含重复的组合。
示例 1: 输入: k = 3, n = 7 输出: [[1,2,4]]
示例 2: 输入: k = 3, n = 9 输出: [[1,2,6], [1,3,5], [2,3,4]]
本题和上一章组合题基本类似,就是这里限制了组合的范围为[1,9]所以相当于在循环中需要用9来限制循环次数。这里递归结束条件就是找到了和为n的k个数的组合,因此可以设置一个sum惨参数来计算当前的和。每次递归都要伴随着回溯,回溯就是把sum减去当前的元素,path去掉当前元素。剪枝操作在循环条件中和上一题是一致的,就是用9-(path.size())+1,这里还要注意一个隐藏条件,如果当前的sum已经大于要求的n,也可以停止循环了。记住在这个判断里依然要进行回溯。
class Solution {List<List<Integer>> res= new ArrayList<>();LinkedList<Integer> path = new LinkedList<>();public void backTracking(int k, int n, int sum, int startIdx){if(path.size()==k){if(n==sum){ //已有k个数且和为nres.add(new ArrayList<>(path));}return;}for(int i=startIdx;i<=9-(k-path.size())+1;i++){ //进行剪枝,如果sum大于n,结束递归sum+=i;path.add(i);if(sum>n){sum-=i;path.removeLast();return;}backTracking(k, n, sum, i+1);sum-=i;path.removeLast();}}public List<List<Integer>> combinationSum3(int k, int n) {backTracking(k,n,0,1);return res;}
}
17.电话号码的字母组合
给定一个仅包含数字
2-9
的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例 1:
输入:digits = "23" 输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]示例 2:
输入:digits = "" 输出:[]示例 3:
输入:digits = "2" 输出:["a","b","c"]
本题看到的时候比较好奇,字母和数字之间的映射怎么巧妙处理,代码随想录里给出的方法是用map或者二维数组进行映射,2-9都有对应的祖母,0和1用空字符来替代,在java中表示如下:
String[] numString = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
终止条件就是如果startIdx 等于 输入的数字个数(digits.size)了(本来index就是用来遍历digits的)。
class Solution {List<String> res = new ArrayList<>();//涉及大量的字符串拼接,所以这里选择更为高效的 StringBuildStringBuilder temp = 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 res;}backTracking(digits, 0);return res;}public void backTracking(String digits, int startIdx){if(startIdx==digits.length()){// 字符串长度length()res.add(temp.toString()); return;}//用str表示数字对应的字符串/*digits.charAt(startIdx)表示当前第startIdx个元素对应的数字,初始值为0如‘23’,startIdx=0,所以当前要取的是‘2’,这里是字符串digits.charAt(startIdx)-'0'表示‘2’与‘0’之间的差值。这样做的目的是将字符数字转换为对应的整数值。所以这里就变成了整数2numString(digits.charAt(startIdx)-'0')对应的就是2所对应的字母‘abc’*/String str=numString[digits.charAt(startIdx)-'0']; for(int i=0;i<str.length();i++){temp.append(str.charAt(i));backTracking(digits, startIdx+1);temp.deleteCharAt(temp.length()-1);}} }