今天的三道题非常有难度五颗星
39:组合总和
错了一次,对回溯算法的理解不够深刻没有想到自增这个过程发生的时间与影响。在此再做复习,所有的回溯算法都可以抽象为树形结构,向下和横向for循环控制的是横向,递归控制的是纵向。切记代码如下:
List<List<Integer>> re = new ArrayList();
List<Integer> path = new ArrayList();
public List<List<Integer>> combinationSum(int[] candidates, int target) {
backTracking(candidates,target,0,0);
return re;
}
public void backTracking(int[] candidates,int target,int sum,int startIndex){
if(sum>target) return;
if(sum==target){
re.add(new ArrayList(path));
return;
}
for(int i=startIndex;i<candidates.length;i++){
sum += candidates[i];
path.add(candidates[i]);
backTracking(candidates,target,sum,i);
sum -=candidates[i];
path.remove(path.size()-1);
}
return;
}
40题:组合总和 II
去重,它来了,本题用到了used数组来去重操作,在横向的也就是for循环控制的部分让之前没有被使用的相同元素直接跳过。纵向的不受影响。很吊代码如下:
List<List<Integer>> re = new ArrayList();
List<Integer> path = new ArrayList();
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
Arrays.sort(candidates);
boolean[] used = new boolean[candidates.length];
backTracking(candidates,target,0,0,used);
return re;
}
public void backTracking(int[] candidates, int target,int sum,int startIndex,boolean[] used){
if(sum>target) return;
if(sum==target){
re.add(new ArrayList(path));
return;
}
for(int i=startIndex;i<candidates.length;i++){
if(i>0&&candidates[i]==candidates[i-1]&&used[i-1]==false){continue;}
sum+=candidates[i];
path.add(candidates[i]);
used[i]=true;
backTracking(candidates,target,sum,i+1,used);
sum-=candidates[i];
path.remove(path.size()-1);
used[i]=false;
}
return;
}
131题:分割回文串
难点在于如何把它放到集合里,还是一样的逻辑。用横向和纵向来判定分割。其实就是遍历所有结果,但是有一个问题就是回溯的终止条件变了,变成了只要指针扫过了所有的集合。很吊,暂时没有理解的特别透彻代码如下:
List<List<String>> lists = new ArrayList<>();
Deque<String> deque = new LinkedList<>();
public List<List<String>> partition(String s) {
backTracking(s, 0);
return lists;
}
private void backTracking(String s, int startIndex) {
//如果起始位置大于s的大小,说明找到了一组分割方案
if (startIndex >= s.length()) {
lists.add(new ArrayList(deque));
return;
}
for (int i = startIndex; i < s.length(); i++) {
//如果是回文子串,则记录
if (isPalindrome(s, startIndex, i)) {
String str = s.substring(startIndex, i + 1);
deque.addLast(str);
} else {
continue;
}
//起始位置后移,保证不重复
backTracking(s, i + 1);
deque.removeLast();
}
}
//判断是否是回文串
private boolean isPalindrome(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;
}