[英]Algorithm for generating all numbers that sum to a given number and its complexity
准备面试时发现以下问题:
3可以写为1 + 1 + 1、1 + 2、2 + 1; 4可以写为1 + 1 + 1 + 1、1 + 1 + 2、2 + 2、1 + 2 + 1、2 + 1 + 1、3 + 1、1 + 3; 给定一个整数,存在多少个可能的表达式? (1 + 2和2 + 1不同)
因此,编写蛮力算法进行计算并获得执行该操作的所有数字集是非常简单的:
private static Set<List<Integer>> getIntegersSum(int num) {
Set<List<Integer>> returnSet = new HashSet<List<Integer>>();
if (num == 0) {
returnSet.add(new LinkedList<Integer>());
return returnSet;
}
for (int i = 1; i <= num; i++) {
Set<List<Integer>> listNMinI = getIntegersSum(num - i);
for (List<Integer> l : listNMinI) {
l.add(0, i);
returnSet.add(l);
}
}
return returnSet;
}
现在,我相信描述此算法复杂性的递归关系为:
T(0) = \Theta (1)
T(n) = O(n) + \Sum_{i=0}^{n-1} T(i)
我不太确定如何从这种递归关系中得出复杂的问题。 我还想知道问题是否有一个封闭式的解决方案(每个数字我们将有多少个类似的组合)。
我也不确定如果我们通过缓存每个调用的结果来记忆该算法(类似于如何加快斐波那契速度)会带来多大的复杂性。
这样的表达式有2 n-1-1个 。
有很多方法可以解决此问题。
我用这个问题的结果:
有n个糖果。 有多少种方法可以将全部n个糖果分配给k个人(可以提供0个糖果)?
顺序很重要,因为这些部分分配给不同的人。 解为(n + k-1)C(k-1)。 我们将k-1个分隔符添加到混合中(使总和为n + k-1),然后尝试找到插入分隔符以将糖果分成k个部分的方法。 考虑将n + k-1个盒子排成一行放置糖果和分隔符,并且我们想找到多种方法来选择k-1个分隔符插槽,从而将盒子分成k个部分。
回到这个问题,我们需要回答这个子问题:
有多少种方法可以将n表达为k个正数之和?
我们可以重用上面糖果分割问题的结果,但是我们需要保留k以防止项为0。因此结果将是((n-k)+ k-1)C(k-1),其中简化为(n-1)C(k-1)。 ((n-k)是由于我们为k个项中的每一个都存放了k)。
因此,最终结果将为Sum [i = 2..n](n-1)C(i-1),因为表达式包含至少2个项,最多包含n个项。 我们知道Sum [i = 1..n](n-1)C(i-1)= 2 n-1 ,所以Sum [i = 2..n](n-1)C(i-1) = 2 n -1-1。
@MarkDickinson在评论中解释了解决此问题的另一种方法。 推理更直接。
在每对糖果之间,没有分隔符或没有分隔符。 这立即给出了
2^(n-1)
可能性。 无论出于什么原因,OP都排除了只有1个部分的单一情况,因此减去1得到2^(n-1) - 1
。
使论点更加扎实。 由于问题仅允许使用正项,因此我们只能在糖果之间插入1个分隔符,并且只能在糖果之间插入它们,而不是2个末端。 因此,在(n-1)个位置可以出现分隔符。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.