回溯算法03(leetcode39/40/131)

参考资料:

https://programmercarl.com/0039.%E7%BB%84%E5%90%88%E6%80%BB%E5%92%8C.html

39. 组合总和

题目描述:

给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。

candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。

对于给定的输入,保证和为 target 的不同组合数少于 150 个。

示例 1:

复制代码
输入:candidates = [2,3,6,7], target = 7
输出:[[2,2,3],[7]]
解释:
2 和 3 可以形成一组候选,2 + 2 + 3 = 7 。注意 2 可以使用多次。
7 也是一个候选, 7 = 7 。
仅有这两种组合

思路分析:

1.先排序,方便剪枝操作

  1. 递归时,起始下标不用 i+1。因为元素可以重复选取

代码实现:

java 复制代码
class Solution {

    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        List<List<Integer>> res=new ArrayList<>();
        //排序
        Arrays.sort(candidates);
        backTracking(res,new ArrayList<>(),candidates,target,0,0);
        return res;
    }

    private void backTracking(List<List<Integer>> res,List<Integer> path,int[] candidates,int target,int sum,int startIndex){
        if(target==sum){
            res.add(new ArrayList<>(path));
            return;
        }

        for(int i=startIndex;i<candidates.length;i++){
            if(sum+candidates[i]>target) break;//剪枝
            path.add(candidates[i]);
            backTracking(res,path,candidates,target,sum+candidates[i],i);
            path.remove(path.size()-1);

        }
    }
}

40. 组合总和 II

题目描述:

给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的每个数字在每个组合中只能使用 一次

**注意:**解集不能包含重复的组合。

示例 1:

复制代码
输入: candidates = [10,1,2,7,6,1,5], target = 8,
输出:
[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]

思路分析:

理解题意:集合不能重复,但集合中可以有数值相同的元素

关键:采用used数组标记,避免相同元素作为起始元素。

if(i>0 && candidatesi==candidatesi-1 && !usedi-1){

continue;

}

代码实现:

java 复制代码
class Solution {
    List<List<Integer>> res=new ArrayList<>();
    List<Integer> path=new LinkedList<>();
    boolean[] used;//标记数组
    int sum=0;

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

    public void backTracking(int[] candidates,int target,int startIndex){
        if(sum==target){
            res.add(new LinkedList<>(path));
        }

        for(int i=startIndex;i<candidates.length;i++){
            if(sum+candidates[i]>target) break;//因为数组已经排好序
            if(i>0 && candidates[i]==candidates[i-1] && !used[i-1]){
                continue;
            }
            used[i]=true;
            sum+=candidates[i];
            path.add(candidates[i]);
            backTracking(candidates,target,i+1);
            used[i]=false;
            sum-=candidates[i];
            path.removeLast();
        }
    }
}

131. 分割回文串

题目描述:

给你一个字符串 s,请你将s分割成一些子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。

示例 1:

复制代码
输入:s = "aab"
输出:[["a","a","b"],["aa","b"]]

思路分析:

注意单层递归逻辑

代码实现:

java 复制代码
//回溯 参考:https://www.programmercarl.com/0131.%E5%88%86%E5%89%B2%E5%9B%9E%E6%96%87%E4%B8%B2.html#%E5%85%B6%E4%BB%96%E8%AF%AD%E8%A8%80%E7%89%88%E6%9C%AC
class Solution {
    List<List<String>> lists=new ArrayList<>();
    Deque<String> deque=new LinkedList<>();
    
    public List<List<String>> partition(String s) {
            backTracking(s,0);
            return lists;
    }
    public void backTracking(String s,int startIndex){
        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();//回溯
        }
    }

    public 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;
    }
}
相关推荐
折哥的程序人生 · 物流技术专研8 小时前
Java面试85题图解版 · 特别篇:2026后端高频面试题复盘(算法底层逻辑+高并发架构设计全解析,附Java实战代码)
java·网络·数据库·算法·面试
想吃火锅10059 小时前
【leetcode】14.最长公共前缀js
算法·leetcode·职场和发展
云絮.10 小时前
数据库操作
数据库·mysql·算法·oracle
小林ixn10 小时前
LeetCode 206. 反转链表(迭代 + 递归详解)
算法·leetcode·链表
凡人叶枫11 小时前
Effective C++ 条款17:以独立语句将 newed 对象置入智能指针
java·linux·开发语言·c++·算法
菜鸟‍12 小时前
LeetCode 1 27 和 704 || 两数之和 移除元素 二分查找
算法·leetcode·职场和发展
退休倒计时13 小时前
【每日一题】LeetCode 142. 环形链表 II TypeScript
算法·leetcode·链表·typescript
popcorn_min14 小时前
Digits 手写数字识别:随机森林多分类 + 像素级特征热力图
算法·随机森林·分类
liulilittle14 小时前
拥塞控制:排水终止的两种决策:OR 与 AND
网络·tcp/ip·计算机网络·算法·信息与通信·tcp·通信
weixin_3077791315 小时前
从脚本执行到智能体协作:AI辅助测试能力的范式重构
运维·开发语言·人工智能·算法·测试用例