39. 组合总和

该文章介绍了如何使用Java编程解决力扣上的一个组合问题,主要方法是递归和回溯。在递归函数isCombinationSun中,根据当前目标值和已选数字进行组合,当目标值为0时得到一个有效组合,目标值不为0则继续尝试。在递归过程中,通过for循环选择当前数字并更新目标值,同时在回溯时删除无效的候选数字以恢复状态。最终,所有有效组合存储在result列表中返回。
摘要由CSDN通过智能技术生成

题目链接:力扣

 解题思路:递归+回溯

  1. 定义递归函数:isCombinationSun(int[] candidates, int target, List<Integer> tem, List<List<Integer>> result, int index):表示在当前待选择的数为candidates[index],与已经选择过的数字进行组合,target表示还剩多少需要进行组合,tem表示已经选择的组合,result保存所有有效的答案:
    1. 递归终止条件:
      1. 如果target==0,则已经成功组合成target,此时tem中保存的既是一个答案,将tem加入到result中
      2. 如果index==candidates.length,说明所有的candidates中的元素已经使用完了,直接return
    2. 令k = target / candidates[index],k表示最多可以选用candidates[index]多少次
    3. 本次递归可以不选用candidates[index]进行组合,进入递归isCombinationSun(candidates, target, tem, result, index + 1)
    4. 本次递归选用candidates[index]进行组合,最多只能选用k次,for循环k次:
      1. tem.add(candidates[index])
      2. target -= candidates[index];
      3. isCombinationSun(candidates, target, tem, result, index + 1)。进入下一层递归,在下一层递归中又会对candidates[index+1]进行选择0次或者多次组合,注意,这里当进入下一次for循环时,即从这里的递归返回时,需要将在isCombinationSun(candidates, target, tem, result, index + 1)递归后面所有新加入的候选数字从tem中删除,因为,本轮中重新选择的候选数字,显然后续递归中的所有候选都已经失效了,也就是回溯的意义!
    5. 回溯
      1. 依次将本轮递归中新加入到tem中的candidates[index]删除,回退到上一轮递归
      2. 删除本轮递归中新加入的candidates[index],在回退到上一轮递归时,上一轮中会重新选择新的候选数字加入到tem中,所以本轮递归中选择的候选数字就变成无效的了,需要从tem中删除,当本轮选择的候选数字是有效组合中的其中一个,那么在回溯删除之前,已经把有效的tem加入到result中了,删除本轮递归中新加入的candidates[index],并不会影响已经找到的答案
  2. AC代码
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class Solution {

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

    public static void isCombinationSun(int[] candidates, int target, List<Integer> tem, List<List<Integer>> result, int index) {
        if (target == 0) {
            result.add(new LinkedList<>(tem));
            return;
        }
        if (index == candidates.length) {
            return;
        }

        int k = target / candidates[index];

        int len = tem.size();
        isCombinationSun(candidates, target, tem, result, index + 1);
        for (int i = 0; i < k; i++) {

            tem.add(candidates[index]);
            target -= candidates[index];
            isCombinationSun(candidates, target, tem, result, index + 1);
        }

        int newLen = tem.size();
        for (int i = 0; i < newLen - len; i++) {
            tem.remove(newLen - i - 1);
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值