【Leetcode】39. 组合总和

43 阅读2分钟

题目描述

在这里插入图片描述

// 39. 组合总和

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

// 说明:
// 所有数字(包括 target)都是正整数。
// 解集不能包含重复的组合。 

题解

// 回溯搜索法
// 同类方法里一个很好的题目。
// 构建答案保存位res用于保存List,构建数字组合保存List combination,
// 递归调用backtracking,输入候选人数组nums,目标数target,答案保存位res,
// 数字组合保存List combination,以及回溯搜索的搜索起点索引,初始化为0。
// 最后返回res。
//
// 下面来定义回溯搜索函数backtracking,函数输入为候选人数组nums,目标数target,
// 答案保存位res,数字组合保存List combination,回溯搜索的搜索起点索引start。
// 老样子,递归函数,先写递归终止条件,是当target为0时(因为后面要用target减去
// 候选数来更新下一次搜索的target),说明搜索的组合符合条件,将combination中
// 元素用ArrayList包装存入res中,return脱离递归,向上回溯。
// 
// for循环从搜索起始点start开始一直遍历到nums的尾部,遍历值为nums[i],
// 如果nums[i]小于等于target,说明可能可以构成组合,将nums[i]暂存入combination,
// 递归调用backtracking,由于nums[i]已经被算入数字和中,所以target-nums[i]
// 为下一次搜索的target,搜索起点索引设置为for循环的当前遍历位i。
// 如果递归回来,则说明刚刚放入的nums[i]的情况已经经过排查,此时在combination中
// 去除刚刚存入的nums[i],然后for循环会继续遍历下一个nums[i],重复刚刚的操作。
//
// 执行用时:2 ms, 在所有 Java 提交中击败了99.93%的用户
// 内存消耗:38 MB, 在所有 Java 提交中击败了99.98%的用户
class Solution {
    public List<List<Integer>> combinationSum(int[] nums, int target) {
        List<List<Integer>> res = new ArrayList<>();
		List<Integer> combination = new ArrayList<>();
        backtracking(nums, target, res, combination, 0);
		return res;
    }
	
	private void backtracking(int[] nums, int target, List<List<Integer>> res, List<Integer> combination, int start) {
		if (target == 0) {
			res.add(new ArrayList<>(combination));
			return;
		}
		for (int i = start; i < nums.length; i++) {
			if (nums[i] <= target) {
				combination.add(nums[i]);
				backtracking(nums, target - nums[i], res, combination, i);
				combination.remove(combination.size() - 1);
			}
		}
	}						
}