排列組合 從n個自然數中取出r個數的組合

這種題目一般有兩種方法,比較直接的方法就是使用循壞,但是對於這種方法只有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,
通過對這個題目的深入瞭解和探究,對遞歸有了較深的認識。

                   

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章