遞迴解決排列組合問題

2021-08-17 10:48:15 字數 2817 閱讀 4651

排列組合是組合學最基本的概念。所謂排列,就是指從給定個數的元素中取出指定個數的元素進行排序。組合則是指從給定個數的元素中僅僅取出指定個數的元素,不考慮排序。

詳細定義參考:

在各種演算法比賽,或面試題中經常會出現關於排列組合的演算法題,這裡總結幾種典型解法來給大家參考

如果是簡單的排列計數問題可以通過數學公式進行計算,但如果題目的是帶條件的計數問題,或者排列列舉問題,就可以使用遞迴加以解決

設集合a[1,2,3],全擺列集合a

[1 2 3] 1-》2得到2 1 3

[1 2 3] 1-》3得到3 2 1

[1 2 3] 2-》3得到1 3 2

由上面的例子我們可以得到全排的大體思路

1.選定乙個元素與其他元素交換位置

2.選定下乙個元素與剩下的交換位置

(每次交換元素位置錢之前要復原)

重複上述過程直到沒有元素可選

例:輸出0-9的全排列

/**

* 全排列0-9

* @author administrator

* */

public class main ;

//static int b = new int[10];

public static void main(string args)

static void f(int n)

system.out.println();

return;

} for(int i = n ; i < a.length ; i++);//選定乙個元素與其他元素交換位置

f(n+1);//選定下乙個元素與剩下的交換位置

;//下次交換之前復原

} }}

上面的就是典型的元素不重複的全排列問題,當列舉完成的時候同時也完成了計數,可以在出口處新增條件來解決類似剪郵票的問題,先暴力列舉所有情況,然後根據條件過濾結果

這裡的問題等價於在乙個元素不重複集合中隨機取n個元素,得到所有取數的可能性,我們把前n個元素依次與後面的元素交換,就可以等到所有可能的情況

類似的,元素不重複的部分排列問題也可以由遞迴解決

/**

* 從3個元素中,取兩個元素

* @author administrator

* */

public class main ;

//static int b = new int[10];

public static void main(string args)

static void f(int n)

system.out.println();

return;

} for(int i = n ; i < a.length ; i++);

f(n+1);

;} }

}

接下來是有重複元素的排列問題

設有m(m!=0)個蘋果,先要求取n(n!=0)個有多少種取法

利用公式 f(m,n) = f(m-1,n-1)+f(m-1,n)遞迴解決

ps:假設蘋果s被取出有f(m,n-1),假設蘋果s未被取出有f(m-1,n)

/**

* 元素不重複組合計數問題

* @author administrator

* */

public class main

static int f(int m,int n)

}

當元素不重複且固定的時候,可以用多重迴圈列舉出來,可當固定時就需要用遞迴了。

例:從abcde選取三個字元

/**

* 元素不重複組合列舉問題

* @author administrator

* */

public class main }

static listf(string s , int n)

//相似性

for(int i = 0 ; i < s.length() ; i++)

}return l;

}}

例:選取aaabbc中的任意三個字母

思路一:假設字串不重複,取出所有組合,用set集合去重

思路二:用int陣列儲存abc可能存在的最大次數,在遞迴中將最大可能和要取的數中進行比較,利用遞迴得到abc出現的次數所有可能儲存到陣列中,最後利用work()輸出

/**

* 元素重複組合列舉問題

* 選取aaabbc中的任意三個字母

* @author administrator

* */

public class main ;

int x = new int[data.length];

f(data,x,0,3);

} /**

* @param data : 字母允許出現的最大次數

* @param x : 結果集中字母出現的次數

* @param k : 當前位置

* @param goal : 當前需要取的字母個數

*/static void f(int data , int x , int k , int goal)

for(int i = 0 ; i <=math.min(data[k], goal);i++)

x[k] = 0;//回溯

} /**

* * @param x : x陣列中記錄了每乙個字母出現的次數

*/static void work(int x)

} system.out.println();

}}

例題:派遣問題

演算法 遞迴思想解決排列組合問題

演算法 遞迴思想解決排列組合問題 直接上 void astring m char str,char pbegin void astring char str 提供的公共介面函式 void cstring m char pstr,int m,vector result result.push back...

C C 排列組合問題(遞迴)

1 問題描述 乙個mxn的矩形,從左下角走到右上角有多少種走法。include include using namespace std void luxian int alen,int blen,char p 100 int ai,int bi,int num const int alen 5 co...

遞迴實現排列組合問題

臨近acm大賽了,博主正在複習遞迴,畢竟博主是乙個菜鳥,對遞迴總是有太多的疑問,所以蒐羅了一些資料集中細談一下用遞迴處理的排列組合問題 題目 用遞迴演算法輸出cn m 從m中取n個數 的每一次的值 如下 include using namespace std int n,m,n n,m為題中的n,m...