生成系列

时间:2014-07-02 10:01:59

标签: java c# .net algorithm permutation

我正在寻找以下问题的解释

给定一个输入 - 整数数组,例如1 2 3 4我想生成所有可能的“排列”,看起来像这个0 0 0 1 , 0 0 0 2,第一个就是这样,直到0 0 0 4,下一个看起来像这个0 0 1 0然后是0 0 1 1。我希望你明白我的观点。我已经构建了一个迭代算法来生成序列,但它对于大小为10的输入使用了太多的内存,我正在寻找的解决方案不使用递归。请注意,有(n + 1)! (0,0,0,0 included)个可能性。

输入仅限于整数,并且始终生成的值的计数等于输入值的计数。

修改

请注意,Stackoverflow中可能有这样的解决方案,但我无法真正为问题定义一个正确的名称,这就是为什么如果有人知道如何实际命名这个问题,请分享! 谢谢!

2 个答案:

答案 0 :(得分:0)

考虑使用iterators来避免存储每个生成的值。

答案 1 :(得分:0)

要生成你的系列,你基本上是这样做的:

  • 从仅包含正确长度的零的数组开始
  • 迭代,并且对于每次迭代,执行“基本数学”,例如数字的递增,就好像数组的每个元素是更大数字的单个数字一样。
    • 基本上将最后一个数字增加1
    • 如果最终高于该位置的最大值,请将其重置为0并向左移动数字
    • 如果它没有达到最高值,那么你就得到了一个新的解决方案
    • 当向左移动到数字的操作从阵列的左端落下时,你已经完成了

这是一个LINQPad解决方案,演示了:

void Main()
{
    CountedPermutations(1, 2, 3)
        .Select(l => new { a = l[0], b = l[1], c = l[2] })
        .Dump();
}

public static IEnumerable<int[]> CountedPermutations(params int[] maxValues)
{
    int[] results = new int[maxValues.Length];

    yield return results; // the all-zeroes solution
    while (true)
    {
        // Increment to next solution
        if (CountedPermutationsMutate(results, maxValues))
        {
            // make a copy of the array and yield return it
            // we make copies so that if the outside code puts everything in a
            // collection, we don't just end up with N references to the same array
            // with the same values.
            yield return results.ToArray();
        }
        else
            break;
    }
}

public static bool CountedPermutationsMutate(int[] values, int[] maxValues)
{
    int index = values.Length - 1;
    bool gotSolution;

    while (true)
    {
        if (values[index] < maxValues[index])
        {
            // won't overflow this position, so we got a new solution
            values[index]++;
            gotSolution = true;
            break;
        }
        else
        {
            // Overflow in this position, reset to 0
            // and move on to the next digit to the left
            values[index] = 0;
            index--;

            // If we fell off the left end of the array, we're done
            if (index < 0)
            {
                gotSolution = false;
                break;
            }
        }
    }

    return gotSolution;
}

这将输出:

0 0 0 
0 0 1 
0 0 2 
0 0 3 
0 1 0 
0 1 1 
0 1 2 
0 1 3 
0 2 0 
0 2 1 
0 2 2 
0 2 3 
1 0 0 
1 0 1 
1 0 2 
1 0 3 
1 1 0 
1 1 1 
1 1 2 
1 1 3 
1 2 0 
1 2 1 
1 2 2 
1 2 3