Java
Arrays.sort(数组) //排序
不讲究顺序的解答,都可以考虑一下排序是否可行。
39. 组合总和
错误解答
在写的时候需要注意,sum -= candidates[i];
很重要,也是回溯的一部分。
解答重复了。是因为回溯的for循环理解错了。
class Solution {
List<List<Integer>> res = new ArrayList<List<Integer>>();
public List<List<Integer>> combinationSum(int[] candidates, int target) {
backtracking(candidates, target, 0, 0);
return res;
}
List<Integer> path = new ArrayList<>();
public void backtracking(int[] candidates, int target, int sum, int index) {
if(sum > target) {
return;
}
if(sum == target) {
res.add(new ArrayList<>(path));
return;
}
for(int i=0; i<candidates.length; i++) {
sum += candidates[i];
path.add(candidates[i]);
backtracking(candidates,target,sum,i);
sum -= candidates[i];
path.remove(path.size()-1);
}
}
}
正确
- 修改成下面这样就对了
优化
不讲究顺序的解答,都可以考虑一下排序是否可行。
剪枝要先排序。
class Solution {
List<List<Integer>> res = new ArrayList<List<Integer>>();
public List<List<Integer>> combinationSum(int[] candidates, int target) {
Arrays.sort(candidates);
backtracking(candidates, target, 0, 0);
return res;
}
List<Integer> path = new ArrayList<>();
public void backtracking(int[] candidates, int target, int sum, int index) {
if(sum == target) {
res.add(new ArrayList<>(path));
return;
}
for(int i=index; i<candidates.length; i++) {
sum += candidates[i];
if (sum > target) break;
path.add(candidates[i]);
backtracking(candidates,target,sum,i);
sum -= candidates[i];
path.remove(path.size()-1);
}
}
}
40.组合总和II
错误解法
想得太简单了……
class Solution {
List<List<Integer>> res = new ArrayList<List<Integer>>();
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
Arrays.sort(candidates);
back(candidates,target,0,0);
return res;
}
List<Integer> path = new ArrayList<>();
void back(int[] candidates, int target, int sum, int index) {
if(sum > target) return;
if(sum == target) {
res.add(new ArrayList(path));
}
for(int i=index; i<candidates.length; i++) {
path.add(candidates[i]);
sum+=candidates[i];
back(candidates,target,sum,index+1);
sum-=candidates[i];
path.remove(path.size()-1);
}
}
}
与之前题目的区别
之前这两题,原本的数组中的元素是不重复的。但本题(40)是重复的,也就是说,[1,1,7],target=8那会有两种情况[1,7] [1,7],但这个答案是重复的,需要去重。
正确解法
本题中可以有重复的元素,因为数组中的元素是重复的。
去重是在同一树层中去除。但树层中怎么去重呢?用到了use数组。
class Solution {
List<List<Integer>> res = new ArrayList<List<Integer>>();
Boolean[] used;
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
used = new Boolean[candidates.length];
Arrays.fill(used, false);
Arrays.sort(candidates);
back(candidates,target,0,0);
return res;
}
List<Integer> path = new ArrayList<>();
void back(int[] candidates, int target, int sum, int index) {
if(sum == target) {
res.add(new ArrayList(path));
}
for(int i=index; i<candidates.length; i++) {
if(i>0 && candidates[i]==candidates[i-1] && !used[i-1]) {
continue;
}
if(sum > target) break; //去重-树枝
path.add(candidates[i]);
sum+=candidates[i];
used[i] = true;
back(candidates,target,sum,i+1);
sum-=candidates[i];
used[i] = false;
path.remove(path.size()-1);
}
}
}
思考:代码中,这个continue什么意思?这里可不可以写return?不可以。
131.分割回文串
那么难究竟难在什么地方呢?
切割问题可以抽象为组合问题
如何模拟那些切割线
切割问题中递归如何终止
在递归循环中如何截取子串
如何判断回文
- 注意
第二十行,为什么还要continue?
因为ab不是回文,没准aba就是了。
而且也不用担心当前不是回文,之后不是怎么办,因为可以切割出单个字符
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;
}
void backtracking(String s, int startIndex) {
if(startIndex == s.length()) {
res.add(new ArrayList(path));
return;
}
for(int i=startIndex; i<s.length(); i++) {
if(ishuiwen(s,startIndex,i)) {
String str = s.substring(startIndex, i + 1);
path.add(str);
} else {
continue;
}
backtracking(s,i+1);
path.removeLast();
}
}
Boolean ishuiwen(String s, int left, int right) {
for(int i=left,j=right; i<=j; i++, j--) {
if(s.charAt(i) != s.charAt(j)) {
return false;
}
}
return true;
}
}