LeetCode刷题day26| 39. 组合总和、40.组合总和II、131.分割回文串

一、39. 组合总和

这道题没有想到剪枝优化。这里在剪枝之前会先将数组进行排序,如果当前元素加入sum之后超过target值,则后边的元素也一定会超过,直接break跳出循环
以下是代码部分:

public class 组合总和39 {

    //这道题虽然做出来了,但是感觉理解的不是很透彻,
    List<List<Integer>> result = new ArrayList<>();
    List<Integer> path = new ArrayList<>();
	//剪枝优化
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {

        if(candidates.length == 0)
            return result;

        //首先要对给定的数组按升序排序
        Arrays.sort(candidates);

        backtracking2(candidates, target, 0);

        return result;
    }

    private void backtracking2(int[] candidates, int target, int start){

        if(target == 0){
            result.add(new ArrayList<>(path));
            return;
        }

        for (int i = start; i < candidates.length; i++) {
            /*
            剪枝操作
             */
            if(target - candidates[i] < 0)
                break;
            path.add(candidates[i]);
            backtracking2(candidates, target-candidates[i], i);
            path.remove(path.size()-1);
        }
    }
}

二、40.组合总和II

这道题不会,没有想出来如何在搜索的过程中去重。
题解中,要深刻理解是在同一树层上去重,还是在同一树枝上去重。本题按题意,是在同一树层上去重。
额外定义一个used数组,用于标识当前数组中哪些元素已经使用过。如果是在同一树枝上,前边的元素使用过,used标识为true,说明正在同一树枝上进行操作,不需要去重。如果是在同一树层中,由于前边的元素会进行回溯,重新标识为false,所以如果当前元素与前一个元素相同,则需要去重。
在同一树层中,如果前边相同的元素已经考虑过情况,那么就不需要再考虑当前的元素了,直接return。
以下是代码部分:

public class 组合总和Ⅱ40 {

    //想不出来,直接看的题解

    List<List<Integer>> result = new ArrayList<>();
    List<Integer> path = new ArrayList<>();
    boolean[] used;

    public List<List<Integer>> combinationSum2(int[] candidates, int target) {

        used = new boolean[candidates.length];

        //需要先进行一个排序,将相同的元素放在一块
        Arrays.sort(candidates);

        backtracking(candidates, target, 0);

        return result;
    }

    private void backtracking(int[] candidates, int target, int startIndex){

        if(target == 0){
            result.add(new ArrayList<>(path));
            return;
        }

        for(int i = startIndex;i < candidates.length; i++){

            //剪枝操作
            if(target - candidates[i] < 0)
                break;

            //对同一层的元素进行去重
            if( i >0 && candidates[i-1] == candidates[i] && used[i-1] == false)     //踩坑,需要从i=1开始判断
                continue;

            path.add(candidates[i]);
            used[i] = true;
            backtracking(candidates, target - candidates[i], i+1);
            path.remove(path.size()-1);
            used[i] = false;
        }
    }
}

三、131.分割回文串

分割问题其实是和组合问题非常像的。

可以把切割线看作是组合问题里的数,也就是说选择某几个符合题意的切割线,每次都是选择i作为切割线。[startIndex,i]是一个选择了右边界之后的区间

以下是代码部分:

public class 分割回文串131 {

    //分割问题其实是和组合问题非常像的
    //可以把切割线看作是组合问题里的数,也就是说选择某几个符合题意的切割线
    List<List<String>> result = new ArrayList<>();
    List<String> path = new ArrayList<>();

    public List<List<String>> partition(String s) {

        backtracking(s, 0);

        return result;
    }

    private void backtracking(String s, int startIndex){

        //收集结果
        //startIndex是切割的起始位置(即当前还可以选择的切割点,如果等于了字符串的长度,证明没有办法再切割了)
        if(startIndex == s.length()){
            result.add(new ArrayList<>(path));
            return;
        }

        for(int i = startIndex; i < s.length(); i++){

            //这里其实就是跟组合问题类似,每次都是选择i作为分割点。[startIndex,i]是一个选择了右边界之后的区间。
            String ss = s.substring(startIndex, i+1);      //这里要+1,左闭右开
            if(isHui(ss))
                path.add(ss);
            else
                continue;

            backtracking(s, i+1);
            path.remove(path.size()-1);

        }
    }

    private boolean isHui(String s){

        for (int i = 0,j = s.length()-1; i < j ; i++,j--) {
            if(s.charAt(i)!=s.charAt(j))
                return false;
        }
        return true;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值