【回溯】【leetCode高频】:39. 组合总和

1、题目描述

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

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

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

 

 

 2、算法分析

本题属于回溯算法题型中的组合求和问题,而且数组中的元素可以重复使用。

回溯算法其实就是暴力的递归求解算法。重点的是N叉树的递归思想。子结点到父节点的递归。

 

回溯算法大概有以下几种题型:

组合,排序,子集,切割,棋牌等。

本题是求数组中的组合的和等于target目标值。

注意:组合中的元素可以重复使用。下面分析这道题。

集合存储结果集,path存储单个路径。

 

①回溯函数参数的确定

回溯函数的返回值一般是void,函数名是backTracking(int[] candidates,int target,int sum,int startIndex)

sum代表的是每一个路径的和

startIndex,因为是组合,比如 12 21其实都是一个组合,组合是无序的。设定startIndex是为了去除重复的值。

②递归结束条件

sum > target的时候直接break;

sum == target的时候,说明找到了符合条件的路径,添加进去

③单层搜索

for循环的i要从startIndex开始,因为是去重。

然后将元素添加到path中,sum += candidate[i];

递归,然后回溯。

剪枝操作:

先对数组进行排序,如果发现sum + candidate[i] > target,也就是下一层的元素大于target,那么直接结束循环。

回溯模板:

复制代码
void backtracking(参数) {
    if (终止条件) {
        存放结果;
        return;
    }
 
    for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
        处理节点;
        backtracking(路径,选择列表); // 递归
        回溯,撤销处理结果
    }
}
复制代码

 3、代码实现

复制代码
 1 class Solution {
 2     List<List<Integer>> result = new ArrayList<>();
 3     List<Integer> path = new ArrayList<>();
 4         
 5     public List<List<Integer>> combinationSum(int[] candidates, int target) {
 6         Arrays.sort(candidates);
 7         backTracking(candidates,target,0,0);
 8         return result;    
 9     }
10     //回溯函数
11     public void backTracking(int[] candidates,int target,int sum,int start){
12         if(sum > target){
13             return;
14         }
15         if(sum == target){
16             result.add(new ArrayList<>(path));
17             return;
18         }
19         for(int i = start;i < candidates.length;i++){
20             if(sum + candidates[i] > target){
21                 break;
22             }
23             path.add(candidates[i]);
24             sum += candidates[i];
25             // 递归
26             backTracking(candidates,target,sum,i);
27             // 回溯
28             sum -= candidates[i];
29             path.remove(path.size() - 1);
30         }
31 
32     }
33 }
复制代码

 

posted on   晓风残月一望关河萧索  阅读(53)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示