三道题套路解决递归问题 | lyl's blog (lyl0724.github.io)
public class Solution {
List<List<Integer>> res = new ArrayList<>();
//使用removeLast()必须是LinkedList
//再说了增删肯定LinkedList更方便
//就是不知道为啥这么写不对List<Integer> path = new LinkedList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> combine(int n, int k) {
if (k <= 0 || n < k) {
return res;
}
// 从 1 开始是题目的设定
dfs(n, k, 1);
return res;
}
public void dfs(int n, int k, int begin) {
if (path.size() == k) {
res.add(new ArrayList<>(path));
}
for (int i = begin; i <= n; i++) {
//又不接收返回值,自然和用addLast()是一样的
path.add(i);
//其实什么都没做, 返回的是return
//近循环了哦,具体看截图
dfs(n, k, i + 1);
path.removeLast();
}
}
}
// void backtracking(参数) {
// if (终止条件) {
// 存放结果;
// return;
// }
// for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
// 处理节点;
// backtracking(路径,选择列表); // 递归
// 回溯,撤销处理结果
// }
// }
// class Solution {
// List<Integer> temp = new ArrayList<Integer>();
// List<List<Integer>> res = new ArrayList<List<Integer>>();
// public List<List<Integer>> combine(int n, int k) {
// dfs(1, n, k);
// return res;
// }
// public void dfs(int cur, int n, int k) {
// // 剪枝:temp 长度加上区间 [cur, n] 的长度小于 k,不可能构造出长度为 k 的 temp
// if (temp.size() + (n - cur + 1) < k) {
// return;
// }
// // 记录合法的答案
// if (temp.size() == k) {
// res.add(new ArrayList<Integer>(temp));
// return;
// }
// // 考虑选择当前位置
// temp.add(cur);
// dfs(cur + 1, n, k);
// temp.remove(temp.size() - 1);
// // 考虑不选择当前位置
// dfs(cur + 1, n, k);
// }
// }
class Solution {
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> temp = new LinkedList<>();
public List<List<Integer>> combinationSum(int[] candidates, int target) {
dfs(candidates, target, 0, 0);
return res;
}
public void dfs(int[] candidates, int target, int begin, int sum) {
if (sum >= target) {
if (sum == target) res.add(new ArrayList<>(temp));
return;
}
for (int i = begin; i < candidates.length; i++) {
temp.add(candidates[i]);
dfs(candidates, target, i, sum + candidates[i]);
temp.remove(temp.size() - 1);
}
}
}
// // 剪枝优化
// class Solution {
// public List<List<Integer>> combinationSum(int[] candidates, int target) {
// List<List<Integer>> res = new ArrayList<>();
// Arrays.sort(candidates); // 先进行排序
// backtracking(res, new ArrayList<>(), candidates, target, 0, 0);
// return res;
// }
// public void backtracking(List<List<Integer>> res, List<Integer> path, int[] candidates, int target, int sum, int idx) {
// // 找到了数字和为 target 的组合
// if (sum == target) {
// res.add(new ArrayList<>(path));
// return;
// }
// for (int i = idx; i < candidates.length; i++) {
// // 如果 sum + candidates[i] > target 就终止遍历
// if (sum + candidates[i] > target) break;
// path.add(candidates[i]);
// backtracking(res, path, candidates, target, sum + candidates[i], i);
// path.remove(path.size() - 1); // 回溯,移除路径 path 最后一个元素
// }
// }
// }
class Solution {
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> temp = new LinkedList<>();
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
Arrays.sort(candidates);
dfs(candidates, target, 0, 0);
return res;
}
public void dfs(int[] candidates, int target, int index, int sum) {
if (sum >= target) {
if (sum == target) res.add(new ArrayList<>(temp));
return;
}
for (int i = index; i < candidates.length; i++) {
if (i > index && candidates[i] == candidates[i - 1]) continue;
temp.add(candidates[i]);
dfs(candidates, target, i + 1, sum + candidates[i]);
temp.remove(temp.size() - 1);
}
}
}
class Solution {
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> temp = new LinkedList<>();
public List<List<Integer>> combinationSum3(int k, int n) {
if (k > 9) return res;
dfs(k, n, 1, 0);
return res;
}
public void dfs(int k, int targetSum, int begin, int sum) {
if (temp.size() == k) {
if (sum == targetSum) res.add(new ArrayList<>(temp));
return;
}
for (int i = begin; i <= 9; i++) {
temp.add(i);
sum += i;
dfs(k, targetSum, i + 1, sum);
temp.removeLast();
sum -= i;
}
}
}
// class Solution {
// List<List<Integer>> result = new ArrayList<>();
// LinkedList<Integer> path = new LinkedList<>();
// public List<List<Integer>> combinationSum3(int k, int n) {
// backTracking(n, k, 1, 0);
// return result;
// }
// private void backTracking(int targetSum, int k, int startIndex, int sum) {
// // 减枝
// if (sum > targetSum) {
// return;
// }
// if (path.size() == k) {
// if (sum == targetSum) result.add(new ArrayList<>(path));
// return;
// }
// // 减枝 9 - (k - path.size()) + 1
// for (int i = startIndex; i <= 9 - (k - path.size()) + 1; i++) {
// path.add(i);
// sum += i;
// backTracking(targetSum, k, i + 1, sum);
// //回溯
// path.removeLast();
// //回溯
// sum -= i;
// }
// }
// }
//递归是一种算法,回溯是一种思想
class Solution {
public List<String> letterCombinations(String digits) {
//要返回的集合
List<String> res = new ArrayList<>();
int len = digits.length();
if (len == 0) 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");
backtrack(res, map, digits, 0, new StringBuilder());
return res;
}
public void backtrack(List<String> res, Map<Character, String> map, String digits, int index, StringBuilder stringBuilder){
if (index == digits.length()) {
res.add(stringBuilder.toString());
} else {
char c = digits.charAt(index);
String value = map.get(c);
int len = value.length();
for (int i = 0; i < len; i++) {
stringBuilder.append(value.charAt(i));
backtrack(res, map, digits, index + 1, stringBuilder);
stringBuilder.deleteCharAt(index);
}
}
}
}
class Solution {
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> temp = new LinkedList<>();
public List<List<Integer>> subsets(int[] nums) {
dfs(nums, 0);
return res;
}
public void dfs(int[] nums, int index) {
res.add(new ArrayList<>(temp));
for (int i = index; i < nums.length; i++) {
temp.add(nums[i]);
dfs(nums, i + 1);
temp.remove(temp.size() - 1);
}
}
}
class Solution {
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> temp = new LinkedList<>();
public List<List<Integer>> subsetsWithDup(int[] nums) {
Arrays.sort(nums);
dfs(nums, 0);
return res;
}
public void dfs(int[] nums, int index) {
res.add(new ArrayList<>(temp));
for (int i = index; i < nums.length; i++) {
//排序后这样,跳过重复的
//for里面是层序遍历做的事情,dfs才是深度遍历做的事情
if (i > index && nums[i] == nums[i - 1]) continue;
temp.add(nums[i]);
dfs(nums, i + 1);
temp.remove(temp.size() - 1);
}
}
}
class Solution {
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> temp = new LinkedList<>();
public List<List<Integer>> findSubsequences(int[] nums) {
if (nums.length < 2) return res;
dfs(nums, 0);
return res;
}
public void dfs(int[] nums, int index) {
if (temp.size() >= 2) {
res.add(new ArrayList<>(temp));
}
for (int i = index; i < nums.length; i++) {
if (i > index && nums[i] == nums[i - 1]) continue;
if (i == index) temp.add(nums[i]);
if (!temp.isEmpty() || (i > 0 && nums[i] >= nums[i - 1])) temp.add(nums[i]);
//什么情况下放进去,和什么情况下跳过是一个意思,要仔细理解一下
//符合情况的全部放进去,和到不符合条件的时候出去是一个意思呀
dfs(nums, i + 1);
temp.remove(temp.size() - 1);
}
}
}
class Solution {
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> temp = new LinkedList<>();
boolean[] used;
public List<List<Integer>> permute(int[] nums) {
used = new boolean[nums.length];
dfs(nums);
return res;
}
public void dfs(int[] nums) {
if (temp.size() == nums.length) {
res.add(new ArrayList<>(temp));
return;
}
for (int i = 0; i < nums.length; i++) {
if (used[i]) continue;
used[i] = true;
temp.add(nums[i]);
dfs(nums);
temp.removeLast();
used[i] = false;
}
}
}
class Solution {
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> temp = new LinkedList<>();
boolean[] used;
public List<List<Integer>> permuteUnique(int[] nums) {
used = new boolean[nums.length];
Arrays.sort(nums);
dfs(nums);
return res;
}
public void dfs(int[] nums) {
if (temp.size() == nums.length) {
res.add(new ArrayList<>(temp));
}
for (int i = 0; i < nums.length; i++) {
if (used[i]) continue;
// used[i - 1] == true,说明同⼀树⽀nums[i - 1]使⽤过
// used[i - 1] == false,说明同⼀树层nums[i - 1]使⽤过
// 如果同⼀树层nums[i - 1]使⽤过则直接跳过
if (i > 0 && nums[i] == nums[i - 1] && !used[i - 1]) continue;
used[i] = true;
temp.add(nums[i]);
dfs(nums);
temp.removeLast();
used[i] = false;
}
}
}