刷题的日常-组合总和

99 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第30天,点击查看活动详情

刷题的日常-2022年8月25日

一天一题,保持脑子清爽

组合总和

来自leetcode的 39 题,题意如下:

给你一个 无重复元素 的整数数组candidates 和一个目标整数target,找出candidates中可以使数字和为目标数target 的 所有不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。
candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。
对于给定的输入,保证和为target 的不同组合数少于 150 个。

示例如下:

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

理解题意

我们可以从题意中提取的条件如下:

  • 题目给定一个数组和一个目标值
  • 要求我们对数组中的数进行组合
  • 如果组合出来的元素的和等于 target,将元素放进结果集
  • 返回所有符合条件的组合

做题思路

组合题,用回溯就可以做,我们不断进行尝试,从前往后遍历,遍历的过程中如果能够匹配成功,加入结果集

  • 进行回溯,我们可以通过排序来减少搜索次数
  • 如果到结尾了也没有匹配成功,不需要操作
  • 如果匹配成功,将其加入结果
  • 如果出现和大于目标值,不需要进行操作
  • 最后返回所有结果

代码实现

代码实现如下:

public class Solution {

    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        Arrays.sort(candidates);
        List<List<Integer>> result = new LinkedList<>();
        combinationSum(candidates, 0, 0, target, result, new ArrayList<>());
        return result;
    }

    private void combinationSum(int[] candidates, int index, int sum, int target, List<List<Integer>> result, List<Integer> item) {
        if (index == candidates.length) {
            return;
        }
        if (sum > target) {
            return;
        }
        if (sum == target) {
            result.add(item);
            return;
        }
        ArrayList<Integer> tmp = new ArrayList<>(item);
        tmp.add(candidates[index]);
        combinationSum(candidates, index, sum + candidates[index], target, result, tmp);
        combinationSum(candidates, index + 1, sum, target, result, item);
    }

}