組合(從長度為n的字串中取m個字元)---java兩種實現方法
阿新 • • 發佈:2019-01-23
對於這類組合問題,雖然感覺很簡單,但是用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];
}