组合总和

题目链接:

涉及知识:回溯,剪枝

分析:

本题为典型的回溯算法。

在一般的情况下,如果不考虑每一个数字可以重复使用多次的话,那么对于每一个元素便只有两种情况,取或者不取。然后再对不符合条件的情况进行判断,剪枝即可。

在本题中,由于每一个元素可以无限次被使用,因此每一个元素需要被判断多次。

注意:由于题目中规定不可以包含重复的组合,因此不可以取当前元素之前已经取过的元素。

例如:2、3、5、8、9;在取 5 的时候,不可以返回去再取 2 或 3。表达的不是很清楚,就先意会一下吧。

代码:

import java.util.ArrayList;
import java.util.List;

/*
 * @lc app=leetcode.cn id=39 lang=java
 *
 * [39] 组合总和
 */
class Solution {
    public List<List<Integer>> resList = new ArrayList<>();
    public int target = 0;
    public int[] candidates;
    public int len = 0;
    
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        this.target = target;
        this.candidates = candidates;
        this.len = candidates.length;
        dfs(new ArrayList<>(), 0, 0);
        
        return resList;
    }

    /**
     * @param list 记录已经取到的元素
     * @param level 表示从第几个元素开始
     * @param sum 记录当前数组中元素的值的总和
     */
    public void dfs(ArrayList<Integer> list, int level, int sum){
        //判断是否达到目标值或者已经超过目标值来剪枝
        if(sum == target){
            resList.add(new ArrayList<>(list));
            return;
        } else if(sum > target){
            return;
        }

        //从 level 开始便保证了不会取到重复的组合
        for(int i = level; i < len; ++i){
            list.add(candidates[i]);
            dfs(list, i, sum + candidates[i]);
            list.remove(list.size() - 1);
        }
        return;
    }
}
原文地址:https://www.cnblogs.com/zcxhaha/p/11454746.html