[英]permutations of certain digits in Java
我意识到编程语言的排列是一个非常常见的问题,但是我觉得我的问题有点独特。
我已经接收到一定长度整数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
的最大值)。
问题是,如何在不使用某种String
串联的情况下获取digits数组的所有排列并返回Long[]
或long[]
? 有没有办法在“事物的整数范围”中返回具有digits[]
所有排列的long[]
,或者仅使用整数算术?
要详细说明上述评论之一,将数字d放在结果long中的给定位置很容易: d*1
将其放在1s位置, d*1000
将其放在数千的位置,通常d * (10^k)
将d
放入第k + 1个数字。 您需要填充N个总位数,因此需要对10的幂进行从1到10 ^(N-1)的排列。
如果您仍然期望排列是Long
,而不是将n
表示为一个计数数组,那么将其表示为Long
可能会更容易。
您可以通过以下两种方式生成排列。
可以考虑将排列生成为查找具有相同数字集的下一个最大数字,该数字从n
的排序数字组成的数字开始。 在这种情况下, 此StackOverflow问题的答案很有帮助。 您可以使用算术运算和修饰来代替字符串串联来实现该算法(如果您愿意,我可以提供更多详细信息)。 这样做的好处是,您生成的排列将自动按顺序排列。
如果您不关心排列的顺序,并且希望数字重复的数目很小,则可以使用Steinhaus-Johnson-Trotter算法,该算法(根据Robert Sedgewick所述 )是生成序列的最快的算法。独特的元素。 为了不产生不确定的重复排列,你就必须区分每一个重复的数字,只发出他们按顺序出现(即,如果排列2
出现三次,然后创建元素2_1
, 2_2
, 2_3
并确保这三个元素始终按发出的排列顺序出现)。
对于要求,假设N的长度为n,我们可以通过从数字到数字(从0开始到n-1结束)生成所有排列。
对于每个数字,我们只经历一次每个可能性(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]++;
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.