对于这类组合问题,虽然感觉很简单,但是用java代码实现起来却不是那么容易的。
这其中最容易用到的应该是递归的思想了,这种方法也比较容易理解:
方法一:
递归实现代码:
/**
* 可能种类在4000万的时候时间效率为7.6s左右
* @param headIndex:当前所要添加字符在原始字符串中的index
* @param length:当前字符串长度
* @param inStr:原始字符串
* @param res:当前字符串
* @param n:所要组合的字符串长度
*/
public static void DiguiZuhe(int headIndex,int length,String inStr,String res,int n){
String s = res;
for (int i = headIndex; i < inStr.length() + length - n; i++) {
if (length <= n) {
res = res + inStr.substring(i, i + 1);
DiguiZuhe(i + 1, length + 1, inStr, res, n);
if (length == n) {
System.out.println(res);
}
}else {
return;
}
res = s;
}
}
//-------------------------------分割线-----------------------------
public static void main(String[] args) {
String inStr = "abcdefg";
int n = 3;
String res = "";
DiguiZuhe(0, 1, inStr, res, n);
}
方法二:
/**
* * 具体思路:将我们的原始的字符串用01数组来代替,0表示没有,1表示有
* 例如:字符串:abcdefg;01数组:[1110000]->abc;[1010100]->ace
* 长度为n的字符串,取m个字符
* 首先会初始化一个01数组,长度为n,前m数字为1,后面n-m个数字为0
* 然后扫描01数组,每一次发现10的时候,都给它变为01,同时将左边的1都移动到最左边,已经是最左边了就不移动,
* 继续扫描直到所有的1都移动到了最右边
* 例如:
* 1 1 1 0 0
* 1 1 0 1 0
* 1 0 1 1 0
* 0 1 1 1 0
* 1 1 0 0 1
* 1 0 1 0 1
* 0 1 1 0 1
* 1 0 0 1 1
* 0 1 0 1 1
* 0 0 1 1 1
* 纯算法时间效率:可能种类在4千万左右时间为1.2s左右
* @param input
* @param strNum
* @return
*/
public static void Combination(String input,int strNum){
int length = input.length();
int[] array = new int[length];
//如果长度相等,就只有一种可能
if (length == strNum) {
System.out.println(input);
return;
}else {
//初始化数组
for (int i = 0; i < length; i++) {
if (i <= strNum -1) {
array[i] = 1;
}else {
array[i] = 0;
}
}
}
while(isContainOneZero(array)){
transform(array);
//将01组成的数组转化为字符串,本来这种算法比较高效的,但是在这里转为String字符串的时候(当数据量特别大的时候)
//主要时间开销就在这里了
StringBuffer res = new StringBuffer();
for (int i = 0; i < array.length; i++) {
if (array[i] == 1) {
//拼接起来
res.append(input.charAt(i));
}
}
System.out.println(res.toString());
}
}
/**
* 验证是否包含10
* @param array
* @return
*/
public static boolean isContainOneZero(int[] array){
for (int i = 0; i < array.length - 1; i++) {
if (array[i] == 1 && array[i + 1] == 0) {
return true;
}
}
return false;
}
/**
* 验证是否所有的1都移到了最左边
* @param array
* @param i
* @return
*/
public static boolean validate(int[] array,int i){
for (int j = 0; j < i; j++) {
if (array[j] == 0 && array[j + 1] == 1) {
return true;
}
}
return false;
}
/**
* 转换数组
* @param array
*/
public static void transform(int[] array){
for (int i = 0; i < array.length - 1; i++) {
if (array[i] == 1 && array[i + 1] == 0) {
swap(array, i, i + 1);
int n = getOneNum(array, i);
for (int j = 0; j < i; j++) {
if (j <= n - 1) {
array[j] = 1;
}else {
array[j] = 0;
}
}
return;
}
}
}
/**
* 获取1的数量
* @param array
* @param i
* @return
*/
public static int getOneNum(int[] array,int i){
int num = 0;
for (int j = 0; j < i; j++) {
if (array[j] == 1) {
num++;
}
}
return num;
}
/**
* 交换方法
* @param array
* @param a
* @param b
*/
public static void swap(int[] array,int a,int b){
array[a] = array[a] + array[b];
array[b] = array[a] - array[b];
array[a] = array[a] - array[b];
}