【问题标题】:Algorithm to find all permutations of a given N with condition找到给定 N 的所有排列的算法
【发布时间】:2011-11-22 05:29:21
【问题描述】:

我正在设计一个程序来打印给定 N 的所有排列,这样每个数字都应该大于下一个数字。

例如 如果 N=3: 输出应为 123,456,789,134,145,178,189 等...

初始设计:

  1. 生成所有可能的排列

  2. 将生成的排列传递给检查条件的数字提取函数

  3. 打印结果

这是一个非常幼稚的算法。但由于 N 的动态大小,我不知道实现/初始设计。

【问题讨论】:

  • 是你想要的所有 N 位十进制数字的集合吗?
  • @TedHopp Yes..N 是函数的给定输入...

标签: java c algorithm permutation


【解决方案1】:

由于 N 总是小于 10,所以我使用了递归

调用函数为f(3,0,0)

public static void f(int N,int digit,int num)
    {
        if(N > 0 )
        {
            for(int d = digit + 1; d < 11 - N; d++) // earlier d < 10, see comments
            {
                f(N-1,d,num * 10 + d);
            }
        }else {
            System.out.println(num); //add it to a list or whatever
        }
    }

输出:

123
124
...
678
679
689
789

【讨论】:

  • +1 做得很好。通过将for 循环中的d &lt; 10 替换为d &lt; 11 - N,可以避免很多无用的工作(尤其是对于大N)。
【解决方案2】:

最直接的方法是使用递归。假设您生成了前 n 个数字,而生成的最后一个数字是 i。您还有 N - n 个数字要生成,它们必须以 i + 1 或更高开头。由于最后一位不能超过 9,所以下一位不能超过 10 - (N - n)。这给出了递归的基本规则。像这样的东西(在 Java 中)应该可以工作:

void generate(int N) {
    int[] generated = new int[N];
    generate(generated, 0);
}

void generate(int[] generated, int nGenerated) {
    if (nGenerated == generated.length) {
        // print the generated digits
        for (int g : generated) {
            System.out.print(g);
        }
        System.out.println();
        return;
    }
    int max = 10 - (generated.length - nGenerated);
    int min = nGenerated == 0 ? 1 : (generated[nGenerated - 1] + 1);
    for (int i = min; i <= max; ++i) {
        generated[nGenerated] = i;
        generate(generated, nGenerated + 1);
    }
}

【讨论】:

    【解决方案3】:

    只需按字典顺序生成它们:

    123
    124
    125
    ...
    134
    135
    ...
    145
    ...
    234
    235
    ...
    245
    ...
    345
    

    这假设您最多有 5 个数字。对于更大范围的 B,请继续。执行此操作的一些简单代码是:

    nextW = w;
    for (int i=n-1; i>=0; --i) {
        // THE LARGEST THE iTH DIGIT CAN BE IS B-(n-i-1)
        // OTHERWISE YOU CANNOT KEEP INCREASING AFTERWARDS
        // WITHOUT USING A NUMBER LARGER THAN B
        if w[i]<B-(n-i-1) {
            // INCREMENT THE RIGHTMOST POSITION YOU CAN
            nextW[i] = w[i]+1;
            // MAKE THE SEQUENCE FROM THERE INCREASE BY 1
            for (int j=i+1; j<N; ++j) {
                nextW[j] = w[i]+j-i+1;
            }
            // VOILA
            return nextW;
        }
    }
    return NULL;
    

    w = [1,2,3,...,N]; 开始(使用for 循环很容易制作),打印w,使用w 作为输入调用上面的函数,打印它,然后继续。使用N = 3B = 5,答案将是上面的列表(没有... 行)。

    如果没有绑定B,那么你就是 SOL,因为有无限多。

    一般来说,您正在计算 Nth elementary symmetric function e_N

    【讨论】:

    • @thinkcool 见上文。如果不清楚,请告诉我哪个部分很麻烦。
    • nextW = w; w 最初包含什么?
    • w = [1,2,3,...,N]开始,然后使用上述函数按字典顺序生成下一个,该函数以w为输入。
    • 我认为我们不需要 B,因为我们只需要打印所有三位数字..
    • @thinkcool 没有B 有无数个。例如,1 2 3、1 2 4、1 2 5、1 2 6、1 2 7、1 2 8、1 2 9、1 2 10、1 2 11、1 2 12、1 2 13、1 2 14 , 1 2 15, 1 2 16, 1 2 17, 1 2 18, 1 2 19, 1 2 20, 1 2 21, 1 2 22, 1 2 23, 1 2 24, 1 2 25, 1 2 26, 1 2 27, 1 2 28, 1 2 29, 1 2 30, 1 2 31, 1 2 32, 1 2 33, 1 2 34, 1 2 35, 1 2 36, 1 2 37, 1 2 38, 1 2 39 , 1 2 40, 1 2 41, 1 2 42, 1 2 43, 1 2 44, 1 2 45, 1 2 46, 1 2 47, 1 2 48, 1 2 49, 1 2 50, 1 2 51, 1 2 52, 1 2 53, 1 2 54, 1 2 55, 1 2 56, 1 2 57, 1 2 58, 1 2 59, 1 2 60, 1 2 61, 1 2 62, 1 2 63, 1 2 64 , 1 2 65, 1 2 66, 1 2 67, 达到字符限制
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-08-17
    • 1970-01-01
    • 2021-04-14
    • 1970-01-01
    • 2012-07-26
    • 2014-09-05
    • 2022-10-17
    相关资源
    最近更新 更多