【随想录】Day27—第七章 回溯算法part03


题目1: 组合总和


1- 思路

回溯三部曲

  • 本题目中,同一 path 下的元素可以重复使用,因此在回溯过程中传入的 startIndex 参数不需要进行 +1 去重操作。
  • 1. 回溯函数参数及返回值
    • candidates:数组
    • startIndex:控制回溯树上同层元素去重——>通过 i = startIndex 实现
    • target:目标值
    • nowSum:当前和
  • 2. 回溯终止&&结果收集
    • 如果 nowSum > target 则终止
    • 如果 nowSum == target 收集结果
  • 3. 回溯逻辑
    • 因为本题在同一个 path 上的回溯无需去重,因此 在递归过程 i 无需 +1
    • 因此每次 对 nowSum 和 path 进行更新
    • 回溯 nowSum 和 path

2- 题解

⭐ 组合总和 ——题解思路

在这里插入图片描述

class Solution {
    List<List<Integer>> res = new ArrayList<>();
    List<Integer> path = new ArrayList<>();
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        backTracing(candidates,0,target,0);
        return res;
    }

    public void backTracing(int[] candidates,int startIndex,int target,int nowSum){
        if(nowSum>target){
            return ;
        }

        if(nowSum==target){
            res.add(new ArrayList(path));
            return;
        }

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

题目2: 组合总和II


1- 思路

本题区别于 组合总和 的点在于,此时要对重复的元素进行去重的逻辑

  • 本质上是树层去重

难点在于去重逻辑

  • 因为是树层去重,所以去重逻辑在 for 循环中
  • 其中为什么是 if( i > 0 && nums[i]==nums[i-1] && used[i-1] ==0)
    • used[i-1] ==0 是因为 该步骤实现的是书层去重,如果是 used[i-1] ==1 的话比如相邻元素[1,1,2] 此时会使得在同一路径上 会去重 1 ,此时是不符合题目逻辑的,因为题目如果 target是4实际上 1 1 2 这个组合是符合逻辑的,因此做的是 树层 去重 而不是 树枝 去重

2- 题解

⭐组合总和 II ——题解思路

在这里插入图片描述

class Solution {
    List<List<Integer>> res = new ArrayList<>();
    List<Integer> path = new ArrayList<>();

    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        int[] used = new int[candidates.length];
        Arrays.fill(used,0);
        Arrays.sort(candidates);
        backTracing(candidates,target,used,0,0);
        return res;
    }

    public void backTracing(int[] candidates,int target,int[] used,int nowSum,int startIndex){
        // 终止
        if(nowSum > target){
            return ;
        }
        if(nowSum == target){
            res.add(new ArrayList(path));
            return ;
        }

        // 单层
        for(int i = startIndex;i<candidates.length;i++){
            if(i>0 && candidates[i] == candidates[i-1] && used[i-1] == 0){
                continue;
            }

            path.add(candidates[i]);
            used[i] = 1;
            nowSum+=candidates[i];
            backTracing(candidates,target,used,nowSum,i+1);
            nowSum-=candidates[i];
            path.removeLast();
            used[i] = 0;
        }
    }
}

题目3: 分割回文串


1- 思路

该回溯的方法实际上是对字符串进行分割,回溯的目标是找分割点
区别在于 for 循环的具体回溯过程

  • 如果 String 在回溯过程中,子串满足 回文条件(通过自定义判断是否回文)
  • 则 分割字符串 ——> path 收集结果 ——> 递归 ——> 回溯
  • 否则 continue

2- 题解

⭐分割回文串 ——题解思路

在这里插入图片描述

class Solution {
    List<String> path = new ArrayList<>();
    List<List<String>> res= new ArrayList<>();

    public List<List<String>> partition(String s) {
        backTracing(s,0);
        return res;
    }

    public void backTracing(String s,int startIndex){
        if(startIndex==s.length()){
            res.add(new ArrayList(path));
            return ;
        }

        // 单层回溯
        for(int i = startIndex;i<s.length();i++){
            if(isPlainDrome(s,startIndex,i)){
                String str = s.substring(startIndex,i+1);
                path.add(str);
                backTracing(s,i+1);
                path.remove(path.size()-1);
            }else{
                continue;
            }
        }
    }

    public boolean isPlainDrome(String s,int left,int right){
        for(;left<right;left++,right--){
            if(s.charAt(left)!=s.charAt(right)){
                return false;
            }
        }
        return true;
    }
}
  • 16
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值