码迷,mamicode.com
首页 > 其他好文 > 详细

Combination Sum系列问题

时间:2016-05-14 15:32:53      阅读:174      评论:0      收藏:0      [点我收藏+]

标签:

主要使用方法是backtracking。

Combination Sum

Given a set of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.

The same repeated number may be chosen from C unlimited number of times.

Note:

  • All numbers (including target) will be positive integers.
  • Elements in a combination (a1, a2, … , ak) must be in non-descending order. (ie, a1 ≤ a2 ≤ … ≤ ak).
  • The solution set must not contain duplicate combinations.

 

For example, given candidate set 2,3,6,7 and target 7
A solution set is: 
[7] 
[2, 2, 3] 

解答:为了减少许多不必要的循环过程,应该先把candidates排序,这样当目前遍历到的元素和已经大于target时,就可以不必再访问candidates后面的元素,直接退回到上个选择处进行选择。

另外,由于candidates集合中的每个数都可以使用无数次,故每次递归调用都应该从上次加入的元素开始遍历。

public class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        List<List<Integer>> result = new LinkedList<List<Integer>>();
        if (candidates == null || candidates.length == 0) {
            return result;
        }
        Arrays.sort(candidates);
        List<Integer> temp = new LinkedList<Integer>();
        helper(candidates, target, result, temp, 0);
        return result;
    }
    public void helper (int[] candidates, int target, List<List<Integer>> result, List<Integer> temp, int index) {
        if (target == 0) {
            result.add(new LinkedList<Integer>(temp));
            return;
        }
        for (int i = index; i < candidates.length && candidates[i] <= target; i++) {
            temp.add(candidates[i]);
            helper(candidates, target - candidates[i], result, temp, i);  //从上次加入的元素开始遍历
            temp.remove(temp.size() - 1);
        }
    }
}

Combination Sum II

Given a collection of candidate numbers (C) and a target number (T), find all unique combinations in C where the candidate numbers sums to T.

Each number in C may only be used once in the combination.

Note:

  • All numbers (including target) will be positive integers.
  • Elements in a combination (a1, a2, … , ak) must be in non-descending order. (ie, a1 ≤ a2 ≤ … ≤ ak).
  • The solution set must not contain duplicate combinations.

 

For example, given candidate set 10,1,2,7,6,1,5 and target 8
A solution set is: 
[1, 7] 
[1, 2, 5] 
[2, 6] 
[1, 1, 6] 

解答:与上题一样应该先把candidates排序。

这题需要注意的有两点是:

1. 每个元素只能用一次,所以每次递归都应该从当前加入元素的下一个元素开始遍历;

2. 集合中含有重复元素,所以在每次for循环在candidates挑选元素时,应将已经挑选过的元素过滤(因为加入此元素的结果已经加入结果集合),避免集合中结果出现重复。递归中则不用考虑起始点与上个元素是否相同,因为递归是在前面元素确定的情况下加入下一元素,它们在同一结果中。

public class Solution {
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        Arrays.sort(candidates);
        List<List<Integer>> rst = new ArrayList<List<Integer>>();
        List<Integer> temp = new ArrayList<Integer>();
        helper(rst, temp, candidates, target, 0);
        return rst;
    }
    public void helper(List<List<Integer>> rst, List<Integer> temp, int[] candidates, int target, int index) {
        if (target == 0) {
            rst.add(new ArrayList<Integer>(temp));
            return;
        }
        for (int i = index; i < candidates.length && candidates[i] <= target; i++) {
            if (i > index && candidates[i] == candidates[i - 1]) {
                continue;
            }
            temp.add(candidates[i]);
            helper(rst, temp, candidates, target - candidates[i], i + 1);  //从下一个元素开始遍历
            temp.remove(temp.size() - 1);
        }
    }
}

Combination Sum III

Find all possible combinations of k numbers that add up to a number n, given that only numbers from 1 to 9 can be used and each combination should be a unique set of numbers.

Ensure that numbers within the set are sorted in ascending order.

Example 1:

Input: k = 3, n = 7

Output:

[[1,2,4]]

Example 2:

Input: k = 3, n = 9

Output:

[[1,2,6], [1,3,5], [2,3,4]]

解答:可以看做是上题的一种特殊情况, candidates数组中的元素为1到9,且不含重复元素,上题中去重的判断可以去掉。

public class Solution {
    public List<List<Integer>> combinationSum3(int k, int n) {
        List<List<Integer>> rst = new ArrayList<List<Integer>>();
        List<Integer> temp = new ArrayList<Integer>();
        helper(rst, temp, k, n, 1);
        return rst;
    }
    public void helper(List<List<Integer>> rst, List<Integer> temp, int k, int n, int number) {
        if (k == temp.size() && n == 0) {
            rst.add(new ArrayList<Integer>(temp));
            return;
        }
        for (int i = number; i <= 9 && i <= n; i++) {
            temp.add(i);
            helper(rst, temp, k, n - i, i + 1);
            temp.remove(temp.size() - 1);
        }
    }
}

总结:本题需要注意的是每次递归里面的循环起始点,以及如何避免结果集的重复。



Combination Sum系列问题

标签:

原文地址:http://www.cnblogs.com/shinning/p/5492503.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!