LeetCode: 216.组合总和III
1.思路
结果集收集每个结果,被函数调用需要声明全局变量result和path。
递归法进行广度和深度遍历,深度遍历k层,广度遍历受限于9的数值。传递参数startIndex用以记录每层递归开始的位置。另外,三个参数的传递更方便。
2.代码实现
1// 传入四个参数
2class Solution {
3 List<List<Integer>> result = new ArrayList<>(); // 收集结果的集合
4 LinkedList<Integer> path = new LinkedList<>(); // 收集结果集
5 public List<List<Integer>> combinationSum3(int k, int n) {
6 backtracking(k, n, 1, 0);
7 return result;
8 }
9
10 public void backtracking(int k, int n, int startIndex, int sum) {
11 // sum 大于 n 时,剪枝操作return
12 if (sum > n) {
13 return;
14 }
15 // 长度大于 k 时, 剪枝操作return
16 if (path.size() > k) {
17 return;
18 }
19 // 当长度和总和均满足要求,则将path加入结果集中
20 if (sum == n && path.size() == k) {
21 result.add(new ArrayList<>(path));
22 return;
23 }
24 // for循环进行深度和广度的遍历
25 for (int i = startIndex; i <= 9; i++) {
26 sum += i;
27 path.add(i);
28 backtracking(k, n, i + 1, sum);
29 sum -= i; // 回溯剪枝
30 path.removeLast(); // 回溯剪枝
31 }
32 }
33}
34
35// 传入三个参数可能更容易想到
36class Solution {
37 List<List<Integer>> result = new ArrayList<>(); // 收集结果的集合
38 LinkedList<Integer> path = new LinkedList<>(); // 收集结果集
39 public List<List<Integer>> combinationSum3(int k, int n) {
40 backtracking(k, n, 1);
41 return result;
42 }
43
44 public void backtracking(int k, int n, int startIndex) {
45 // sum 大于 n 时,剪枝操作return
46 if (n < 0 ) {
47 return;
48 }
49 // 长度大于 k 时, 剪枝操作return
50 if (path.size() > k) {
51 return;
52 }
53 // 当长度和总和均满足要求,则将path加入结果集中
54 if (0 == n && path.size() == k) {
55 result.add(new ArrayList<>(path));
56 return;
57 }
58 // for循环进行深度和广度的遍历
59 for (int i = startIndex; i <= 9; i++) {
60 n -= i;
61 path.add(i);
62 backtracking(k, n, i + 1);
63 n += i; // 回溯剪枝
64 path.removeLast(); // 回溯剪枝
65 }
66 }
67}
3.复杂度分析
时间复杂度:O(n*n^2).一次递归查值(深度)对应k次递归和k次for循环,则时间消耗为n^2,n次遍历(广度)则需要n.
空间复杂度:O(k).空间复杂度取决于栈和堆空间的消耗,栈时是递归函数调用的层数k,数组则为O(k).
LeetCode: 17.电话号码的字母组合
1.思路
题意:在一个集合中,选取符合条件的两个元素可能的组合结果。
map映射映或者二维数组均可以存储相应的元素,回溯函数传入需要的参数:digits/numString/num对其进行递归即可.
2.代码实现
1class Solution {
2
3 List<String> list = new ArrayList<>(); // 存储最终结果的列表
4 StringBuilder temp = new StringBuilder(); // 创建字符串???
5
6 public List<String> letterCombinations(String digits) {
7 if (digits == null || digits.length() == 0) { // 数字字符串为空或长度为0 时直接返回
8 return list;
9 }
10 String[] numString = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"}; // 为每个数字对应的字母构建字符数组
11 backTracking(digits, numString, 0); // 递归函数,传入数字字符串digits,字符数组numString, 以及遍历开始位置
12 return list;
13
14 }
15 // 回溯函数
16 public void backTracking(String digits, String[] numString, int num) {
17 // 遍历长度num 等于 数字字符串dights的长度时,将结果转化为字符数组加入list中即可
18 if (num == digits.length()) {
19 list.add(temp.toString()); // 将对象temp转化为字符串表示形式
20 return;
21 }
22 String str = numString[digits.charAt(num) - '0']; // 获取当前数字对应的字母表
23 for (int i = 0; i < str.length(); i++) { // 遍历字母表中的每个字母
24 temp.append(str.charAt(i)); // 将当前字母加入到临时字符串
25 backTracking(digits, numString, num + 1); // 递归调用下一个数字的回溯
26 temp.deleteCharAt(temp.length() - 1); // 递归符合条件之后,删除临时字符串的最后一个字母,进行下一个字母的调用
27 }
28 }
29}
3.复杂度分析
时间复杂度:O(n*2^k).
空间复杂度:O(k+m).k为递归函数的深度或层数,k为字符数组的大小.