leetCode40组合总和(回溯)

题目

复制代码
给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字在每个组合中只能使用 一次

示例 :

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

回溯一般模板

1、会使用深度优先遍历的递归

2、数据是否排序

(1)如果不允许数据重复,要先对数组进行排序,递归的时候,起始节点=当前的index+1,而且

同层相同元素不重复执行

(2)数据允许重复,不用对数组排序,递归的时候,起始节点=当前的index

3、完全递归,把数据恢复到上一个状态,也就是回溯

模板总结

参数说明:

|------------|---------------------------|
| start | 开始的数组下标 |
| candidates | 数组 |
| sum | 达到的条件(这里以数据和为例),具体的按题目要求换 |
| resultList | 所有结果 |
| path | 中间过程,符合要求的一组数据 |

允许数据重复一般模板

复制代码
public static void dfsNum(int start, int[] candidates, int target, int sum, List<List<Integer>> resultList, List<Integer> path) {
    if (结束递归条件) {
        return;
    }
    if (符合要求数据条件) {
        resultList.add(new ArrayList<>(path));
        return;
    }
    for (int i = start; i < candidates.length; i++) {
        if (剪枝条件) {
            break;
        }
        sum += candidates[i];
        path.add(candidates[i]);
        dfsNum(i, candidates, target, sum, resultList, path);
         //回溯,过程中使用的数据,恢复原值
        path.remove(path.size() - 1);
        sum -= candidates[i];
    }
}

不允许数据重复一般模板

复制代码
public static void dfsNum(int start, int[] candidates, int target, int sum, List<List<Integer>> resultList,List<Integer> path) {
 if (结束递归条件) { return; } 
 if (符合要求数据条件) {
    resultList.add(new ArrayList<>(path)); 
     return; 
}
    for (int i = start; i < candidates.length; i++) {
        //最外层重复数据不重复执行
        if (i > start && candidates[i] == candidates[i - 1]) {
            continue;
        }
        if (剪枝条件) {
            break;
        }
        sum += candidates[i];
        path.add(candidates[i]);
        dfsNum(i + 1, candidates, target, sum, resultList, path);
 //回溯,过程中使用的数据,恢复原值
        path.remove(path.size() - 1);
        sum -= candidates[i];
    }
}

实现代码

复制代码
public class ArrayZhSum40 {

    public static void main(String[] args) {
        int[] candidates = {2, 5, 2, 1, 2};
        List<List<Integer>> resultList = combinationSum2(candidates, 5);
        System.out.println(JSON.toJSONString(resultList));
        candidates = new int[]{10, 1, 2, 7, 6, 1, 5};
        resultList = combinationSum2(candidates, 8);
        System.out.println(JSON.toJSONString("---" + resultList));
    }


    public static List<List<Integer>> combinationSum2(int[] candidates, int target) {
        if (candidates == null || candidates.length == 0) {
            return null;
        }
        Arrays.sort(candidates);
        List<List<Integer>> resultList = new ArrayList<>();
        dfsNum(0, candidates, target, 0, resultList,
                new ArrayList<Integer>());
        return resultList;
    }

    public static void dfsNum(int start, int[] candidates, int target, int sum, List<List<Integer>> resultList,
                              List<Integer> path) {
        if (target < sum) {
            return;
        }
        if (target == sum) {
            resultList.add(new ArrayList<>(path));
            return;
        }
        for (int i = start; i < candidates.length; i++) {
           //分层中使用过的元素直接不在用
            if (i > start && candidates[i] == candidates[i - 1]) {
                continue;
            }
            if (candidates[i] > target) {
                break;
            }
            sum += candidates[i];
            path.add(candidates[i]);
            //叶子中,不使用已经使用过的元素
            dfsNum(i + 1, candidates, target, sum, resultList, path);
            path.remove(path.size() - 1);
            sum -= candidates[i];
        }
    }


}
相关推荐
灵感__idea34 分钟前
Hello 算法:“走一步看一步”的智慧
前端·javascript·算法
lwf0061642 小时前
导数学习日记
学习·算法·机器学习
yaoxin5211233 小时前
390. Java IO API - WatchDir 示例
java·前端·python
头发够用的程序员3 小时前
从滑动窗口到矩阵运算:img2col算法基本原理
人工智能·算法·yolo·性能优化·矩阵·边缘计算·jetson
武帝为此3 小时前
【数据清洗缺失值处理】
python·算法·数学建模
Halo_tjn4 小时前
Java 基于字符串相关知识点
java·开发语言·算法
梦想的颜色4 小时前
java 利用redis来限制用户频繁点击
java·开发语言
念越4 小时前
算法每日一题 Day08|双指针法解决三数之和
算法·力扣
黎阳之光5 小时前
黎阳之光透明管理:视频孪生重构智慧仓储新范式
人工智能·算法·安全·重构·数字孪生
PH = 76 小时前
OverlayFS联合文件系统使用示例
java·linux·服务器