這種題目一般有兩種方法,比較直接的方法就是使用循壞,但是對於這種方法只有r小於等於4時纔是可行的,這個時候複雜度是(O(n^r)),可知,這種方法的時間複雜度很高,而且這種循環機制嚴重依賴r,通過r來控制循環層數,因此這種方法不具有普遍性。最常用的方法就是使用遞歸。
在循環算法設計中,每個組合中的數據都是從大到小排列是必須的,因爲遞歸算法設計時要找出大規模問題與小規模問題之間的關係。
當 n = 5, r = 3時,從大到小排列的組合數目是:
5 4 3
5 4 2
5 4 1
5 3 2
5 3 1
5 2 1
4 3 2
4 3 1
3 2 1
總得組合數total = 10;
分析以上數據可以知道,首先固定第一個數5,其後求解n=4,r=2的組合數,共6個組合,其次固定第一個數4,其後就是求解n=3,r=2的組合數,總共是3個組合數;最後固定第一個數3,其後就是求解n=2,r=2的組合數,共一個組合。
遞歸思路就是:n個數中r個數組合遞推到n-1個樹種r-1個數有組合,n-2個數中r-1個數有組合,。。。r-1個數中r-1個數組合;當r=1時,遞歸終止;
package com.base;
public class Permutation {
static int a[] = new int[100];
public static void f(int n,int r){
if(r == 1){
a[r-1] = n;
int j = 0;
while(a[j]!= 0){
j++;
}
for(int i = j-1; i >= 0; i --){
System.out.print(a[i]+",");
}
System.out.println();
}
else{
a[r-1] = n;
for(int j = n-1; j >= r-1; j --){
f(j,r-1);
}
}
}
public static void main(String[] args) {
int n = 6,r = 3;
for(int i = n; i >= r; i --){
f(i,r);
}
}
}
結果如下所示:
6,5,4,
6,5,3,
6,5,2,
6,5,1,
6,4,3,
6,4,2,
6,4,1,
6,3,2,
6,3,1,
6,2,1,
5,4,3,
5,4,2,
5,4,1,
5,3,2,
5,3,1,
5,2,1,
4,3,2,
4,3,1,
4,2,1,
3,2,1,
通過對這個題目的深入瞭解和探究,對遞歸有了較深的認識。