Java中某些数字的排列

时间:2014-03-17 02:22:40

标签: java algorithm recursion permutation dynamic-programming

我意识到编程语言中的排列是一个非常常见的问题,但我觉得我的问题有点独特。

我收到了一定长度整数N的输入,并将每个数字存储在一个数组中,其中数组的索引存储了N中数字出现的次数。

现在我想测试一些函数是否适用于N的原始长度的所有排列而没有前导零。例如:

int[] digits = new int[10];
String n = "12345675533789025";
for (char c : n.toCharArray())
    digits[c-'0']++;
for (Long f : allPermutationsOf(digits))
    if (someCondition(f))
        System.out.println(f);

以下代码的前提条件是N必须小于2 ^ 64-1,(long的最大值。)

问题是,如何在不使用某种Long[]连接的情况下获取数字数组的所有排列并返回long[]String?有没有办法在“整数范围内”中返回long[]所有digits[]的排列,或者只使用整数运算?

3 个答案:

答案 0 :(得分:1)

要详细说明上述评论之一,将数字d放在结果长度中的给定位置很容易:d*1将其置于1s位置,d*1000将其置于数千个位置,通常d * (10^k)d放入第k + 1位。你需要填充N个总数,所以你需要对10的幂进行排列,从1到10 ^(N-1)。

答案 1 :(得分:0)

如果您希望排列为Long,而不是将n表示为计数数组,则将其表示为Long也可能更容易。< / p>

以下是一些可以生成排列的方法。

  1. 考虑将排列生成为查找具有相同数字集的下一个最大数字,从由n的排序数字组成的数字开始。在这种情况下,this StackOverflow question的答案很有帮助。您可以使用算术运算和修改而不是字符串连接来实现那里的算法(如果您愿意,我可以提供更多详细信息)。这样做的好处是,您生成的排列将自动排序。

  2. 如果您不关心排列的顺序,并且您希望数字副本的数量很少,则可以使用Steinhaus-Johnson-Trotter算法(根据{{3 }})是生成唯一元素排列的最快算法。为了确保不生成重复的排列,您必须区分每个重复的数字,并且只发出它们按顺序出现的排列(即,如果2出现三次,则创建元素2_12_22_3并确保这三个元素在发出的排列中始终以该顺序出现。)

答案 2 :(得分:0)

对于要求,假设N的长度为n,我们可以通过从一个数字到另一个数字生成所有排列,从0开始到n-1结束.0是前导数字。

对于每个数字,我们只检查一次可能性(0到9),这样可以避免重复排列。

从数字x到数字x + 1,我们可以通过传递一个名为current的数字

轻松生成当前值

例如:在数字3处,我们有电流= 1234,所以在数字4处,如果我们选择5为数字4,则当前将为1234 * 10 + 5 = 12345

Java中的示例代码:

public void generate(int index, int length, int[] digits, long current, ArrayList<Long> result) {
    //All the permutation will be stored in result ArrayList
    for (int i = 0; i < 10; i++) {
        if (digits[i] > 0 && (i != 0 || index != 0)) {                
            digits[i]--;
            if (index + 1 == length) {//If this is the last digit, add its value into result
                result.add(current * 10 + i);
            } else {//else, go to next digit
                generate(index + 1, length, digits, current * 10 + i, result);
            }
            digits[i]++;
        }
    }
}