【代码随想录刷题笔记】DAY27 第七章 回溯算法

39. 组合总和 

本题是 集合里元素可以用无数次,那么和组合问题的差别 其实仅在于 startIndex上的控制

题目链接/文章讲解:代码随想录

视频讲解:带你学透回溯算法-组合总和(对应「leetcode」力扣题目:39.组合总和)| 回溯法精讲!_哔哩哔哩_bilibili

//回溯三部曲
//可以取重复元素时i的处理
//剪枝,排序, 如果 sum + candidates[i] > target 就终止遍历
//注意这里要add(new LinkedList(path))
class Solution {
    //新建List保存result
    List<List<Integer>> result = new ArrayList<>();
    //新建List保存每次得到的路径path
    LinkedList<Integer> path = new LinkedList<>();
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        // 先进行排序
        Arrays.sort(candidates);
        backtracking(candidates, target, 0, 0);
        return result;        
    }
    
    //定义回溯方法
    private void backtracking(int[] candidates, int target, int startIndex, int sum) {
        //终止条件
        if(sum == target) {
            //!!!注意这里要add(new LinkedList(path))
            //new LinkedList<>(path) will make a copy of path,
            //which will make sure the elements be stored into result.
            //Otherwise, after path.removeLast(), 
            //the elements in result will be removed.
            result.add(new LinkedList(path));
            return;
        }
        //for循环,单层搜索过程
        //如果 sum + candidates[i] > target 就终止遍历
        for(int i = startIndex; i <= candidates.length - 1; i++) {
            if(sum + candidates[i] > target) {break;}
            sum += candidates[i];
            //处理节点
            path.add(candidates[i]);
            //递归;不用i+1了,表示可以重复读取当前的数
            backtracking(candidates, target, i, sum);
            //回溯
            sum -= candidates[i];
            path.removeLast();  
        }       
    }
}

40.组合总和II 

本题开始涉及到一个问题了:去重。

题目链接/文章讲解:代码随想录

视频讲解:回溯算法中的去重,树层去重树枝去重,你弄清楚了没?| LeetCode:40.组合总和II_哔哩哔哩_bilibili

//回溯三部曲
//去重(树层 vs 树枝)
//排序,有利于剪枝和去重
class Solution {
    //新建List保存result
    List<List<Integer>> result = new ArrayList<>();
    //新建List保存每次得到的路径path
    LinkedList<Integer> path = new LinkedList<>();
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        //排序,有利于剪枝和去重
        Arrays.sort(candidates);
        backtracking(candidates, target, 0, 0);
        return result;
    }
    
    //定义回溯方法
    private void backtracking(int[] candidates, int target, int startIndex, int sum) {
        //终止条件
        if(sum == target) {
            result.add(new LinkedList(path));
            return;
        }
        //for循环,单层搜索过程
        for(int i = startIndex; i < candidates.length && sum + candidates[i] <= target; i++ ) {
            //去重
            if(i > startIndex && candidates[i] == candidates[i - 1]) {
                continue;
            }
            //处理节点,更新path
            sum += candidates[i];
            path.add(candidates[i]);
            //递归
            backtracking(candidates, target, i + 1, sum);
            //回溯
            sum -= candidates[i];
            path.removeLast();   
        }
    }
}

131.分割回文串 

代码随想录

视频讲解:带你学透回溯算法-分割回文串(对应力扣题目:131.分割回文串)| 回溯法精讲!_哔哩哔哩_bilibili

//切割问题使用回溯
//用startIndex模拟那些切割线
//切割问题中递归如何终止: startIndex大于s的大小
//在递归循环中如何截取子串加入path: String str = s.substring(startIndex, i + 1)
class Solution {
    //新建List保存result
    List<List<String>> result = new ArrayList<>();
    //新建List保存每次得到的路径path
    LinkedList<String> path = new LinkedList<>();
    public List<List<String>> partition(String s) {
        backtracking(s, 0);
        return result;
    }
    
    //定义回溯方法
    private void backtracking(String s, int startIndex) {
        //终止条件
        //如果起始位置大于s的大小,说明找到了一组分割方案
        if(startIndex >= s.length()) {
            result.add(new LinkedList(path));
            return;
        }
        //for循环,单层搜索过程
        for(int i = startIndex; i < s.length(); i++) {
            //如果是回文子串,则记录
            if(isPalindrome(s, startIndex, i)) {
                //获取[startIndex,i]在s中的子串
                String str = s.substring(startIndex, i + 1);
                path.add(str);
            //不是则下一轮循环    
            } else {
                continue;
            }
            //递归
            backtracking(s, i + 1);
            //回溯
            path.removeLast();
        }      
    }
    
    //定义判断回文方法
    private boolean isPalindrome(String s, int start, int end) {
        for(int i = start, j = end; 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、付费专栏及课程。

余额充值