这就是我的意思。假设S = {1, 4}
和N = 5
。集S
中元素的有序排列就像
{1}, {4}, {1,1}, {1,4}, {4,1}, {4,4}, {1,1,1}, ....
和总计N
的那些
{1,4}, {4, 1}, {1,1,1,1,1}
我想要一种能够有效找到这些算法的算法。
我的“蛮力”方式就像
static IEnumerable<IEnumerable<int>> OrderedArrangements(IEnumerable<int> nums, int k)
{
var singles = nums.Select(i => new int[] {i} );
var cumulative = singles;
for(int j = 2; j <= k; ++j)
{
var last = cumulative.Where(list => list.Count() == (j - 1));
var next = from x in singles
from y in last
select x.Concat(y);
cumulative = cumulative.Concat(next);
}
return cumulative;
}
然后
int sumToN = OrderedArrangements(new int[] {1, 4}, N)
.Where(x => x.Sum() == N);
但我想知道是否有一种明显且更有效的方法来做到这一点。
答案 0 :(得分:1)
如果上面的答案不够清楚,你可以尝试直接递归,例如
...
/ \
(1) (4)
/ \ / \
(1)(4) (1)(4)
static void f(int sum, int n, String str, int[] arr){
if (n == sum){
Console.WriteLine(str);
return;
}
if (n > sum) return;
for (int i = 0; i < arr.Length; i++){
f(sum, n + arr[i], str + arr[i].ToString(), arr);
}
}
static void Main(string[] args){
int[] arr = { 1, 4 };
f(5, 0, "", arr);
}
问题中sum
为N
,n
初始化为0
,str
初始化为""
和{{1}你的问题是arr
。
输出:
S
答案 1 :(得分:0)
这对我有用:
static IEnumerable<IEnumerable<int>> OrderedArrangements(IEnumerable<int> nums, int k)
{
return
k <= 0
? new [] { Enumerable.Empty<int>() }
: nums
.SelectMany(
n => OrderedArrangements(nums, k - n),
(n, ns) => new [] { n }.Concat(ns))
.Where(ns => ns.Sum() == k);
}
OrderedArrangements(new [] { 1, 4 }, 5)
的结果是:
我运行了这个性能测试代码:
Func<Func<IEnumerable<IEnumerable<int>>>, double> measure = f =>
{
var sw = Stopwatch.StartNew();
var result = f();
sw.Stop();
return sw.Elapsed.TotalMilliseconds;
};
var n = 200;
var a = 0.0;
var b = 0.0;
for (var i = 0; i < n; i++)
{
a += measure(() => OrderedArrangements_A(new [] { 1, 4, 9, 13 }, 50000));
b += measure(() => OrderedArrangements_B(new [] { 1, 4, 9, 13 }, 50000));
}
OrderedArrangements_A
是OP的代码,OrderedArrangements_B
是我的。
“A”平均为15.6ms,“B”平均为0.004ms。我的代码运行速度提高了大约3,895倍。