簡體   English   中英

有沒有一種有效的方法可以找到集合 S 中元素的所有有序排列,這些元素加起來為 N?

[英]Is there an efficient way to find all ordered arrangements of elements in the set S that add up to N?

這就是我的意思。 假設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);

但我想知道是否有一種明顯且更有效的方法來做到這一點。

以防萬一上面的答案不夠清楚,您可以嘗試直接遞歸,例如

     ...
    /       \
   (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);
}

在您的問題中sumN時, n被初始化為0str被初始化為""並且arr在您的問題中是S

輸出:

11111
14
41

這對我有用:

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.6 毫秒,“B”的平均時間為 0.004 毫秒。 對於這個測試,我的代碼運行速度快了大約 3,895 倍。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM