day27||第七章 回溯算法part03● 39. 组合总和● 40.组合总和II● 131.分割回文串

● 39. 组合总和

三个问题,第一个是又忘记新建ArrayList赋值到res里面了

第二个是忘记组合的含义了,是无序,也就是startindex的确定,这导致我在答案集合中出现了重复。。。。进入到下一个backTracking后,一定不能再从0开始了。而是从当前元素开始,因为可以重复引用。

最后一个是忘记把sum减去当前的值了。导致结果错误。

class Solution {
    List<Integer> path = new ArrayList<>();
    List<List<Integer>> res = 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 sum,int startIndex){
        if(sum>target){
            return;
        }
        if(sum==target){
            res.add(new ArrayList<>(path));
            return;
        }

        for(int i = startIndex;i<candidates.length;i++){
            path.add(candidates[i]);
            sum+=candidates[i];
            backTracking(candidates,target,sum,i);
            sum-=candidates[i];
            path.remove(path.size()-1);
        }
    }
}

下面加了剪枝,要在for里面做文章,不过要先对数组排序 

class Solution {
    List<Integer> path = new ArrayList<>();
    List<List<Integer>> res = new ArrayList<>();
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        Arrays.sort(candidates);
        backTracking(candidates,target,0,0);
        return res;
    }
    public void backTracking(int[] candidates, int target,int sum,int startIndex){
        if(sum>target){
            return;
        }
        if(sum==target){
            res.add(new ArrayList<>(path));
            return;
        }

        for(int i = startIndex;i<candidates.length&&sum+candidates[i]<=target;i++){
            path.add(candidates[i]);
            sum+=candidates[i];
            backTracking(candidates,target,sum,i);
            sum-=candidates[i];
            path.remove(path.size()-1);
        }
    }
}

● 40.组合总和II

先排序,然后去重,我们要去重的是同一树层上的“使用过”,同一树枝上的都是一个组合里的元素,不用去重

引入了used数组。

 if(i>0&&candidates[i-1]==candidates[i]&&used[i-1]==false){
                continue;
            }

这个终止条件,必须要配合使用,拿【1,1,2】举例,我现在到第二个1了,当我与前面的1相同而且前面的1在此刻没有使用,我才把这个情况排除掉。因为什么呢,当我在处理第一个1的时候,我就已经包含了第二个1的所有情况了。。。。。所以说,第二个1的情况就可以跳过了。

class Solution {
    List<Integer> path = new ArrayList<>();
    List<List<Integer>> res = new ArrayList<>();
    
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        boolean[] used = new boolean[candidates.length];
        Arrays.sort(candidates);
        backTracking(candidates,target,0,0,used);
        return res;
    }
    public void backTracking(int[] candidates,int target, int sum, int startIndex, boolean[] used){
        if(sum>target){
            return;
        }
        if(sum==target){
            res.add(new ArrayList<>(path));
            return;
        }
        for(int i = startIndex;i<candidates.length;i++){
            if(i>0&&candidates[i-1]==candidates[i]&&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;
        }
    }
}

● 131.分割回文串

还是有点没想明白这这分割问题是怎么抽象成回溯问题的。。。。。

substring(左闭右开);

又出现了引用拷贝问题。。。。。

class Solution {
    List<String> path = new ArrayList<>();
    List<List<String>> res= new ArrayList<>();
    public List<List<String>> partition(String s) {
        backTracking(s,0);
        return res;
    }
    public 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(isPalindrome(s,startIndex,i)){
                String str = s.substring(startIndex, i + 1);
                path.add(str);
            }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;
    }
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值