LeetCode:leetcode.cn/problems/co…
1.思路
组合问题,遍历 + 回溯即可。
步骤: ①确定回溯方法及其参数; ②确定单层递归逻辑; ③确定终止条件;
2.代码实现
class Solution {
List<List<Integer>> resList = new ArrayList<>();
List<Integer> path = new ArrayList<>();
public List<List<Integer>> combinationSum(int[] candidates, int target) {
traversal(candidates, target, 0, 0);
return resList;
}
void traversal(int[] candidates, int target, int sum, int startIndex) {
if (sum > target) return;
if (sum == target) {
resList.add(new ArrayList<>(path));
return;
}
for (int i = startIndex; i < candidates.length; i++) {
path.add(candidates[i]);
sum += candidates[i];
traversal(candidates, target, sum, i);
sum -= candidates[i];
path.remove(path.size() - 1);
}
}
}
3.复杂度分析
LeetCode:40. 组合总和 II - 力扣(LeetCode)
1.思路
有重复元素,不允许有重复组合,所以要考虑去重,此时对应的是树层去重,将组合排序,使用used[]标记判断即可。 步骤,回溯三部曲,同上
2.代码实现
class Solution {
// List<Integer> path = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
List<List<Integer>> ans = new ArrayList<>();
boolean[] used;
int sum = 0;
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
// 标记数组
used = new boolean[candidates.length];
Arrays.fill(used, false); // 初始值
Arrays.sort(candidates); // 排序 便于树层去重
backTracking(candidates, target, 0);
return ans;
}
void backTracking(int[] candidates, int target, int startIndex) {
if (sum == target) {
ans.add(new ArrayList<>(path));
}
for (int i = startIndex; i < candidates.length; i++) {
// 剪枝操作
if (sum + candidates[i] > target) {
break;
}
// 树层去重
if (i > 0 && candidates[i] == candidates[i - 1] && !used[i - 1]) {
continue;
}
used[i] = true;
path.add(candidates[i]);
sum += candidates[i];
backTracking(candidates, target, i + 1); // i + 1 递归深度
// 回溯操作
sum -= candidates[i];
used[i] = false;
// path.remove(path.size() - 1);
path.removeLast();
}
}
}
3.复杂度分析
时间复杂度:O(n * 2 ^ n).
空间复杂度:O(n).
LeetCode:
遍历切割字符串,对每个字符串进行判断是否为回文子串,如果不是则跳过递归到下一层,直到遍历结束。 ①确定回溯方法参数及其返回值; ②确定单层递归的逻辑; ③确定终止条件:遍历到字符串尾部。
1.思路
2.代码实现
class Solution {
List<List<String>> resList = new ArrayList<>();
// List<String> list = new ArrayList<>();
// LinkedList<String> list = new LinkedList<>();
Deque<String> list = new LinkedList<>();
public List<List<String>> partition(String s) {
backTracking(s, 0);
return resList;
}
// 分割
public void backTracking(String s, int startIndex) {
if (startIndex >= s.length()) {
resList.add(new ArrayList<>(list));
return;
}
for (int i = startIndex; i < s.length(); i++) {
if (isValid(s, startIndex, i)) {
String str = s.substring(startIndex, i + 1);
list.add(str);
} else {
continue;
}
// 回溯
backTracking(s, i + 1);
// list.remove(list.size() - 1);
list.removeLast();
}
}
// 判断回文子串的方法
public boolean isValid(String s, int startIndex, int end) {
for (int i = startIndex, j = end; i < j; i++, j--) {
if (s.charAt(i) != s.charAt(j)) {
return false;
}
}
return true;
}
}
3.复杂度分析
时间复杂度:O(n * 2^n).
空间复杂度:O(n^2).栈开销取决于递归调用的深度,包括回溯方法和判断回文串的方法。