你如何从给定的N个数字中测试所有可能的加法组合,使它们加起来得到给定的最终数字?
一个简单的例子:
要添加的数字集:N ={1,5,22,15,0,…} 期望结果:12345
你如何从给定的N个数字中测试所有可能的加法组合,使它们加起来得到给定的最终数字?
一个简单的例子:
要添加的数字集:N ={1,5,22,15,0,…} 期望结果:12345
当前回答
c#版本的@msalvadores代码的答案
void Main()
{
int[] numbers = {3,9,8,4,5,7,10};
int target = 15;
sum_up(new List<int>(numbers.ToList()),target);
}
static void sum_up_recursive(List<int> numbers, int target, List<int> part)
{
int s = 0;
foreach (int x in part)
{
s += x;
}
if (s == target)
{
Console.WriteLine("sum(" + string.Join(",", part.Select(n => n.ToString()).ToArray()) + ")=" + target);
}
if (s >= target)
{
return;
}
for (int i = 0;i < numbers.Count;i++)
{
var remaining = new List<int>();
int n = numbers[i];
for (int j = i + 1; j < numbers.Count;j++)
{
remaining.Add(numbers[j]);
}
var part_rec = new List<int>(part);
part_rec.Add(n);
sum_up_recursive(remaining,target,part_rec);
}
}
static void sum_up(List<int> numbers, int target)
{
sum_up_recursive(numbers,target,new List<int>());
}
其他回答
用excel找到组合(相当容易)。 (你的电脑不能太慢)
去这个网站 进入“Sum to Target”页面 下载“Sum to Target”excel文件。 按照网站页面上的说明操作。
希望这能有所帮助。
在Haskell:
filter ((==) 12345 . sum) $ subsequences [1,5,22,15,0,..]
J:
(]#~12345=+/@>)(]<@#~[:#:@i.2^#)1 5 22 15 0 ...
正如您可能注意到的,两者都采用相同的方法,并将问题分为两部分:生成幂集的每个成员,并检查每个成员与目标的和。
还有其他的解决方案,但这是最直接的。
在这两种方法中,你是否需要帮助,或者找到另一种方法?
首先推导0。0是加法的一个恒等式所以在这个特殊情况下,它在单类定律下是没有用的。如果你想向上爬到一个正数,也可以推导出负数。否则还需要做减法运算。
所以…在这个特定的作业中,你能得到的最快算法如下所示。
函数items2T ([n,……ns), t) { Var c = ~~(t/n); 返回ns。长度呢?数组(c + 1) .fill () .reduce((r,_,i) => r.concat(items2T(ns, t-n*i)。map(s => Array(i).fill(n).concat(s))),[]) : t % n ?[] :[数组(c) .fill (n)); }; Var数据= [3,9,8,4,5,7,10], 结果; console.time(“组合”); result = items2T(data, 15); console.timeEnd(“组合”); console.log (JSON.stringify(结果));
这是一个非常快的算法,但如果你对数据数组进行降序排序,它会更快。使用.sort()是无关紧要的,因为算法最终会减少递归调用。
这类似于硬币更换问题
public class CoinCount
{
public static void main(String[] args)
{
int[] coins={1,4,6,2,3,5};
int count=0;
for (int i=0;i<coins.length;i++)
{
count=count+Count(9,coins,i,0);
}
System.out.println(count);
}
public static int Count(int Sum,int[] coins,int index,int curSum)
{
int count=0;
if (index>=coins.length)
return 0;
int sumNow=curSum+coins[index];
if (sumNow>Sum)
return 0;
if (sumNow==Sum)
return 1;
for (int i= index+1;i<coins.length;i++)
count+=Count(Sum,coins,i,sumNow);
return count;
}
}
我想我应该用这个问题的答案,但我不能,所以这是我的答案。它使用的是《计算机程序的结构和解释》中答案的修改版本。我认为这是一个更好的递归解,应该更能取悦纯粹主义者。
我的答案是用Scala(如果我的Scala很烂,我很抱歉,我刚刚开始学习)。findsumcombination的疯狂之处在于对递归的原始列表进行排序和惟一,以防止欺骗。
def findSumCombinations(target: Int, numbers: List[Int]): Int = {
cc(target, numbers.distinct.sortWith(_ < _), List())
}
def cc(target: Int, numbers: List[Int], solution: List[Int]): Int = {
if (target == 0) {println(solution); 1 }
else if (target < 0 || numbers.length == 0) 0
else
cc(target, numbers.tail, solution)
+ cc(target - numbers.head, numbers, numbers.head :: solution)
}
使用它:
> findSumCombinations(12345, List(1,5,22,15,0,..))
* Prints a whole heap of lists that will sum to the target *