39.组合总和
思路:回溯法,将问题抽象为树形结构,使用回溯法解决。
class Solution {
private List<List<Integer>> res = new ArrayList<>();
private List<Integer> path = new ArrayList<>();
public List<List<Integer>> combinationSum(int[] candidates, int target) {
backtracking(candidates, target, 0, 0);
return res;
}
public void backtracking(int[] candidates, int target, int count, int start) {
if (count > target) return; // 剪枝
if (count == target) {
List<Integer> temp = new ArrayList<>(path);
res.add(temp);
return;
}
for (int i = start; i < candidates.length; i++) {
path.add(candidates[i]);
count += candidates[i];
backtracking(candidates, target, count, i);
count -= candidates[i];
path.remove(path.size() - 1);
}
return;
}
}
40.组合总和II
思路:本题与39题大体思路一致,但是本题中存在重复数据,重点在于去重操作。注意去重的时候有两种维度,一种是在同一个树枝上,一种是在同一个树层上,本题需要对同一个树层上使用过的元素进行去重。在同一个树层上进行去重,需要对数组进行排序。
class Solution {
private List<List<Integer>> res = new ArrayList<>();
private List<Integer> path = new ArrayList<>();
public List<List<Integer>> combinationSum2(int[] candidates, int target) { // 重点在去重
// 将数组排序,相同的元素放在一起,方便去重
Arrays.sort(candidates);
backtracking(candidates, target, 0, 0);
return res;
}
public void backtracking(int[] candidates, int target, int count, int start) {
if (count > target) return; // 剪枝
if (count == target) {
List<Integer> temp = new ArrayList<>(path);
res.add(temp);
return;
}
for (int i = start; i < candidates.length; i++) {
// 对同一树层使用过的元素进行去重(跳过相同的元素)
if (i > start && candidates[i] == candidates[i - 1]) {
continue;
}
path.add(candidates[i]);
count += candidates[i];
backtracking(candidates, target, count, i + 1);
count -= candidates[i];
path.remove(path.size() - 1);
}
return;
}
}
131.分割回文串
思路:将问题抽象成树形结构解决,使用回溯法。但要注意,在代码中,递归需要传入的参数startIndex就是字符串的切割线,在单层逻辑的处理中,[startIndex, i] 就是我们要截取的子串。
class Solution {
List<List<String>> res = new ArrayList<>();
List<String> path = new ArrayList<>();
public List<List<String>> partition(String s) {
backtracking(s, 0);
return res;
}
public void backtracking(String s, int start) {
if (start == s.length()) {
res.add(new ArrayList<>(path));
return;
}
for (int i = start; i < s.length(); i++) {
if (isPalindrome(s, start, i)) {
path.add(s.substring(start, i+1));
} else {
continue;
}
backtracking(s, i + 1);
path.remove(path.size() - 1);
}
}
public boolean isPalindrome(String s, int start, int end) {
while (start < end) {
if (s.charAt(start) != s.charAt(end)) return false;
start++;
end--;
}
return true;
}
}