81,092
社区成员
发帖
与我相关
我的任务
分享
package test;
/**
* 求 N 个元素的全排列算法:
* 1. 创建一个大小为 N 个元素的数组.
* 2. 利用 N 进制,满 N 加 1的原则,对数组的第0个元素加 1,满 N 了,则下一个元素值加 1.
* 3. 检查数组中的元素是否有重复的,如果没有,则是一个排列.
* 4. 直到数组中的元素为0, 1, 2, ..., N - 1,则结束,否则继续第2步直到结束.
*/
/**
* 求 N 个元素中 M 个元素的组合算法:
* 1. 创建一个大小为 N 个元素的数组,前 M 个元素为1,后面的 N-M 个元素为0
* 2. 从左向右找到 10 的元素(前一个元素是1,下一个元素是0), 交换这两个元素;
* 把此元素前面的所有1都移动到数组的最前面,此为一个组合,输出.
* 3. 直到前 N-M 个元素都为0,则结束,否则继续第2步直到结束.
*/
public class Combinatory {
public static void produceCombination(String str, int size) {
if (size > str.length()) { throw new IllegalArgumentException("Size is to large."); }
// 创建一个数组,前size个元素全是1
int[] digit = new int[str.length()];
for (int i = 0; i < size; ++i) {
digit[i] = 1;
}
// 输出第一组
printCombination(str, digit);
while (!end(digit, digit.length - size)) {
for (int i = 0; i < digit.length - 1; ++i) {
if (digit[i] == 1 && digit[i + 1] == 0) {
// i上是1,i + 1是0,交换
int temp = digit[i];
digit[i] = digit[i + 1];
digit[i + 1] = temp;
// 移动i前面的所有1到最左端
int count = countOf1(digit, i);
for (int j = 0; j < count; ++j) {
digit[j] = 1;
}
for (int j = count; j < i; ++j) {
digit[j] = 0;
}
printCombination(str, digit);
break;
}
}
}
}
// 在下标end前1的个数
private static int countOf1(int[] digit, int end) {
int count = 0;
for (int i = 0; i < end; ++i) {
if (digit[i] == 1) {
++count;
}
}
return count;
}
// 数组中为1的下标对应的字符需要输出
private static void printCombination(String str, int[] digit) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < digit.length; ++i) {
if (digit[i] == 1) {
sb.append(str.charAt(i));
}
}
System.out.println(sb);
}
// 结束条件:前 size 个元素都是0
private static boolean end(int[] digit, int size) {
int sum = 0;
for (int i = 0; i < size; ++i) {
sum += digit[i];
}
return sum == 0 ? true : false;
}
public static void main(String[] args) {
System.out.println("Start");
String str = "0123456789abcdef";
long appStart = System.currentTimeMillis();
long elapse = 0;
for (int i = 1; i <= str.length(); ++i) {
long start = System.currentTimeMillis();
Combinatory.produceCombination(str, i);
elapse = System.currentTimeMillis() - start;
System.out.printf("Millis: %d, Seconds: %d\n", elapse, elapse / 1000);
}
elapse = System.currentTimeMillis() - appStart;
System.out.printf("Total Millis: %d, Seconds: %d\n", elapse, elapse / 1000);
}
}