您的位置:首页 > 编程语言 > C#

Combination Sum III C#

2015-08-24 09:16 525 查看
Find all possible combinations of k numbers that add up to a numbern, 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]


题意:将一个正整数n拆分成k个数字的累加和,k个数字互不相同且按照升序排列。返回满足条件的k个数字的所有组合。

解析:首先 分析该问题的隐藏条件:因为只能分解成9以内的数字组合,且每个数字都只能出现一次,所以可以,根据抽屉原则,k最大为9,n最大为1+2+3+..+9 = 45,且根据题意k,n都是正整数,还有一个隐藏条件是n / k <= 9;以上条件是这个问题的隐藏条件。

其次,该问题的tag是backtrackings,回溯法的应用,回溯法解决问题的思路是:d(1)作为有可能解决问题的满足要求的第一步可能解,在d(1)的条件下得到有可能解决问题的满足条件的第二步解的解d(2),依次类推,当推到d(N)时出现了不能继续后推得到满足跳进的下一步解时回归到上一步d(N-1),此时d(N-1)换另一个可能解,继续后推,直到所有的d(N-1)的可能解都无法后推出解决此问题的解时,回归到d(N-2)步。

针对这个问题,使用回溯法,要解决两个问题,第一:n分解出的k个数字是按照升序排列的。第二:当 i 进入解集后无法推出有效解的时候,如何回溯到 i 并将代替 i 的下一个可能解加入解集。

代码实现:

public class Solution
{
public List<List<int>> CombinationSum3(int k, int n)
{
List<List<int>> ret = new List<List<int>>();
Stack<int> tmp = new Stack<int>(); // 使用栈的特性来将可能解加入到解集中,并在完成这一可能解的所有后推解的验证后更换下一可能解。
if (k == 0 || n == 0 || n / k > 9 || k > 9 || n >45)
return ret;
help(ret, tmp, 1, k, n);
return ret;
}
public void help(List<List<int>> ret, Stack<int> tmp, int start, int k, int n)
{
if (k == 0 && n == 0)
{
ret.Add(new List<int>(tmp.Reverse()));  // C#中的栈转换成列表是逆序的,所以也需要逆转一下,这也是使算法变慢的一个主要原因。
return;
}
for (int i = start; i <= 9 && k >= 1 && n >= i; i++) // k , n的下限设置不是必须的,但是加上后会有效的减少递归层数。
{
tmp.Push(i);
help(ret, tmp, i + 1, k - 1, n - i);
tmp.Pop();
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息