【回溯&剪枝】力扣Hot100:39. 组合总和题目解析(Java详解)

力扣Hot100题目解析:39. 组合总和(Java详解)

一、题目描述

给定一个无重复元素的数组 candidates 和一个目标数 target,找出 candidates 中所有可以使数字和为 target 的组合。candidates 中的数字可以无限制重复被选取。

示例:

输入: candidates = [2,3,6,7], target = 7
输出: [[7],[2,2,3]]

二、解题思路(回溯+剪枝)

这道题用回溯法(递归+回退)来实现所有可能组合的枚举。

思路详解:

  1. 排序 candidates 数组(便于后续剪枝优化)。
  2. 使用递归函数(回溯)枚举所有可能的组合:
    • 每次递归传入当前的组合列表、剩余的 target 以及当前遍历的起始下标。
    • 如果 target == 0,说明找到一个合法组合,将其加入答案列表。
    • 如果 target < 0,说明当前组合不合法,直接返回。
  3. 递归遍历 candidates,从当前 index 开始(允许元素重复选取),每次选择当前元素并递归下去。
  4. 剪枝优化:如果 candidates 已排序,遇到 candidates[i] > target 时,可以直接 break。

这样可以高效地枚举所有可能的解。

三、Java代码实现(详细注释)

import java.util.*;

public class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        List<List<Integer>> res = new ArrayList<>(); // 存放最终结果
        Arrays.sort(candidates); // 排序,便于剪枝
        backtrack(candidates, target, 0, new ArrayList<>(), res);
        return res;
    }
    // 回溯函数
    private void backtrack(int[] candidates, int target, int start, List<Integer> path, List<List<Integer>> res) {
        // 如果 target 为0,说明找到一个结果
        if (target == 0) {
            res.add(new ArrayList<>(path)); // 注意要复制一份
            return;
        }
        // 遍历所有候选数
        for (int i = start; i < candidates.length; i++) {
            // 剪枝:如果当前数比剩余target大,后面更大,无需再试
            if (candidates[i] > target) break;
            // 选择当前数
            path.add(candidates[i]);
            // 因为可以重复选取,所以递归时start仍为i
            backtrack(candidates, target - candidates[i], i, path, res);
            // 回退,撤销选择
            path.remove(path.size() - 1);
        }
    }
}

代码详解:

  • Arrays.sort(candidates):排序方便剪枝。
  • backtrack递归函数:每次选择一个数,递归搜索剩余部分。
  • 剪枝优化:遇到 candidates[i] > target 时直接跳出循环。
  • 路径回退:每次递归完后要撤销上一次的选择。

四、总结

回溯法是解决组合类、排列类问题的常用技巧,理解递归和剪枝思想可以帮助你高效解决类似问题。

文章标签: 力扣,算法,Java,回溯,剪枝,面试,数组,递归

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值