跳至主要內容

组合总和

刘恩丽2024年12月5日大约 2 分钟教学文档回溯法

组合总和

1. 题目描述

给你一个无重复元素的整数数组 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。仅有这两种组合。

示例 2

输入:candidates = [2,3,5], target = 8
输出:[[2,2,2,2],[2,3,3],[3,5]]

示例 3

输入:candidates = [2], target = 1
输出:[]

2. 分析

可以通过回溯法来解决。我们需要找到所有可能的组合,使得这些组合的和等于目标值 target。由于每个数字可以无限制重复使用,在回溯过程中需要特别注意这一点。

  1. 创建一个结果列表 result,用于存储所有满足条件的组合。创建一个路径列表 path,用于记录当前正在构建的组合。
  2. 定义一个递归函数 backtrack,该函数接受三个参数:当前剩余的目标值 target,当前路径 path,以及当前选择的起始索引 start
    • 终止条件:
      • 如果 target = 0,说明当前路径是一个有效的组合,将其添加到结果列表 result 中。
      • 如果 target < 0,说明当前路径不可能是一个有效的组合,直接返回。
    • 选择列表:
      • 遍历从 start 开始的每个候选数字,将当前数字加入到路径 path 中。
      • 递归调用 backtrack,传入更新后的 targetpath,以及当前选择的索引 start(允许重复选择同一个数字)。
      • 撤销选择,将当前数字从路径 path 中移除,继续尝试其他选择。
  3. 返回结果列表 result

3. 代码

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

    private void backtrack(int[] candidates, int target, int start, List<Integer> path, List<List<Integer>> result) {
        if (target == 0) {
            result.add(new ArrayList<>(path));
            return;
        }
        if (target < 0) {
            return;
        }
        for (int i = start; i < candidates.length; i++) {
            path.add(candidates[i]);
            backtrack(candidates, target - candidates[i], i, path, result);
            path.remove(path.size() - 1);
        }
    }
}
上次编辑于: 2024/12/5 07:41:33
贡献者: Ma Yukai