一、组合总和(LeetCode39)
回溯
class Solution {
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> combinationSum(int[] candidates, int target) {
backtracing(candidates,target,0,0);
return res;
}
void backtracing(int[] candidates,int target,int sum,int index){
if(sum > target) return;
if(sum == target){
res.add(new ArrayList<>(path));
return;
}
for(int i = index;i <= candidates.length-1;i++){
sum += candidates[i];
path.add(candidates[i]);
backtracing(candidates,target,sum,i);//不用i+1,表示可以重复读取当前的数
sum -= candidates[i];
path.removeLast();
}
}
}
优化回溯
class Solution {
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> combinationSum(int[] candidates, int target) {
// Arrays.sort(candidates); // 先进行排序
// 冒泡
for(int i = 0;i<candidates.length;i++){
for(int j = 0;j<candidates.length-i-1;j++){
if(candidates[j] > candidates[j+1]){
int tem = candidates[j+1];
candidates[j+1] = candidates[j];
candidates[j] = tem;
}
}
}
backtracing(candidates,target,0,0);
return res;
}
void backtracing(int[] candidates,int target,int sum,int index){
if(sum > target) return;
if(sum == target){
res.add(new ArrayList<>(path));
return;
}
//剪枝
for(int i = index;i<=candidates.length-1 && sum+candidates[i]<=target;i++){
sum += candidates[i];
path.add(candidates[i]);
backtracing(candidates,target,sum,i);//不用i+1,表示可以重复读取当前的数
sum -= candidates[i];
path.removeLast();// 回溯,移除路径 path 最后一个元素
}
}
}
二、组合总和 II(LeetCode40)
回溯
class Solution {
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
Arrays.sort(candidates);
backtracing(candidates,target,0,0);
return res;
}
void backtracing(int[] candidates,int target,int sum,int index){
if(sum > target) return;
if(sum == target){
res.add(new ArrayList<>(path));
return;
}
for(int i = index;i<=candidates.length-1&&sum+candidates[i]<=target;i++){
// 要对同一树层使用过的元素进行跳过
if (i > index && candidates[i] == candidates[i - 1]) {
continue;
}
sum += candidates[i];
path.add(candidates[i]);
backtracing(candidates,target,sum,i+1);//这里是i+1,每个数字在每个组合中只能使用一次
sum -= candidates[i];
path.removeLast();// 回溯,移除路径 path 最后一个元素
}
}
}
加标志数组判断
class Solution {
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
boolean[] tem = new boolean[candidates.length];
Arrays.fill(tem, false);// 加标志数组,用来辅助判断同层节点是否已经遍历
Arrays.sort(candidates);// 为了将重复的数字都放到一起,所以先进行排序
backtracing(candidates,target,0,0,tem);
return res;
}
void backtracing(int[] candidates,int target,int sum,int index,boolean[] tem){
if(sum > target) return;
if(sum == target){
res.add(new ArrayList<>(path));
return;
}
for(int i = index;i<=candidates.length-1&&sum+candidates[i]<=target;i++){
// 出现重复节点,同层的第一个节点已经被访问过,所以直接跳过
if (i > index && candidates[i] == candidates[i - 1] && !tem[i - 1]) {
continue;
}
tem[i] = true;
sum += candidates[i];
path.add(candidates[i]);
backtracing(candidates,target,sum,i+1,tem);//这里是i+1,每个数字在每个组合中只能使用一次
tem[i] = false;
sum -= candidates[i];
path.removeLast();// 回溯,移除路径 path 最后一个元素
}
}
}
三、分割回文串(LeetCode131)
回溯,截取判断回文
class Solution {
List<List<String>> res = new ArrayList<>();
LinkedList<String> path = new LinkedList<>();
public List<List<String>> partition(String s) {
backtracing(s,0);
return res;
}
void backtracing(String s,int index){
if(index >= s.length()){
res.add(new ArrayList<>(path));
return;
}
for(int i = index;i<s.length();i++){
if (isPalindrome(s, index, i)) { // 是回文子串
// 获取[index,i]在s中的子串
String str = s.substring(index, i + 1);
path.add(str);
} else { // 不是回文,跳过
continue;
}
backtracing(s, i + 1); // 寻找i+1为起始位置的子串
path.removeLast(); // 回溯过程,弹出本次已经填在的子串
}
}
boolean isPalindrome(String s,int start,int end){
for(int i = start,j = end;i<j;i++,j--){
if(s.charAt(i) != s.charAt(j)){
return false;
}
}
return true;
}
}
1032

被折叠的 条评论
为什么被折叠?



