1. LeetCode 77. 组合
题目链接:https://leetcode.cn/problems/combinations/description/
文章链接:https://programmercarl.com/0077.组合.html
视频链接:https://www.bilibili.com/video/BV1ti4y1L7cv
思路:利用递归回溯的方式。
递归回溯树形图如下:
其中,每层代表该层递归的处理逻辑,深度是递归的层数。
解法:
class Solution {
List<List<Integer>> res = new ArrayList<>();
List<Integer> list = new ArrayList<>();
public List<List<Integer>> combine(int n, int k) {
int[] input = new int[n];
for (int i=0;i<n;i++) {
input[i] = i+1;
}
int startIndex = 0;
backtracking(input,k,startIndex);
return res;
}
public void backtracking(int[] input,int k,int startIndex) {
if ( k == 0) {
res.add(new ArrayList(list));
return;
}
for (int i=startIndex;i<input.length;i++) {
list.add(input[i]);// 处理当前节点
backtracking(input,k-1,i+1);
list.removeLast(); // 撤销当前节点
}
}
}
代码解析:
单层处理完当前节点,要记得撤销当前节点,即回溯。这样它才能在当层排除该处理节点,并对其他节点重新进行处理,进行相同的逻辑。
2. LeetCode 216.组合总和III
题目链接:https://leetcode.cn/problems/combination-sum-iii/description/
文章链接:https://programmercarl.com/0216.组合总和III.html
视频链接:https://www.bilibili.com/video/BV1wg411873x
思路:
和77一样。只是加了求和的判断。
解法:
class Solution {
List<Integer> list = new ArrayList<>();
List<List<Integer>> res = new ArrayList<>();
int sum = 0;
public List<List<Integer>> combinationSum3(int k, int n) {
find(n,k,1);
return res;
}
public void find(int n,int k,int startIndex) {
if (list.size() == k && sum == n) {
res.add(new ArrayList(list));
return;
}
for (int i=startIndex;i<=9;i++) {
// 处理节点
list.add(i);
sum+=i;
find(n,k,i+1);
// 撤销节点
list.removeLast();
sum-=i;
}
}
}
3. LeetCode 17.电话号码的字母组合
题目链接:https://leetcode.cn/problems/letter-combinations-of-a-phone-number/
文章链接:https://leetcode.cn/problems/letter-combinations-of-a-phone-number/
视频链接:https://www.bilibili.com/video/BV1yV4y1V7Ug
思路:
使用回溯,但是要注意每层处理的字母集合是不同的集合,因此,每层遍历集合时的索引都是从0开始。
解法:
class Solution {
List<String> res = new ArrayList<>();
String combin = "";
public List<String> letterCombinations(String digits) {
if (digits.length() == 0 || digits == null) {
return res;
}
Map<Character,String> map = new HashMap<>();
map.put('2',"abc");
map.put('3',"def");
map.put('4',"ghi");
map.put('5',"jkl");
map.put('6',"mno");
map.put('7',"pqrs");
map.put('8',"tuv");
map.put('9',"wxyz");
find(digits,0,map);
return res;
}
public void find(String digits,int index,Map<Character,String> map) {
// 终止条件
if (index == digits.length()) {
res.add(combin);
return;
}
// 获取当前层的字母集合,即 当前数字对应的字母集合
String letters = map.get(digits.charAt(index));
// 遍历当前层的字母集合
for (int i=0;i<letters.length();i++) {
// 处理当前字母
combin += letters.charAt(i);
// 递归下一层
find(digits,index+1,map);
// 撤销当前字母 即回溯
combin = combin.substring(0,combin.length()-1);
}
}
}