1. 程式人生 > >0002演算法--------整數劃分問題演算法分析及JAVA程式碼完美實現

0002演算法--------整數劃分問題演算法分析及JAVA程式碼完美實現

整數劃分演算法分析以及JAVA程式碼完美實現 一、問題描述 整數劃分:將正整數n表示成一系列正整數只和,n = n1 + n2 + …… + nk,其中n1 >= n2 >= nk >= 1,k >= 1 。正整數 n 的這種表示稱為正整數 n 的劃分,正整數 n 的所有不同的劃分個數總和稱為正整數 n 的劃分數,記作p(n)。 例如: 正整數 3 有如下3種不同的劃分,即p(n)= 3。 3; 2 + 1; 1 + 1 + 1; 正整數 6 有如下11種不同的劃分,即p(n)= 11。 6; 5 + 1; 4 + 2,4 + 1 + 1; 3 + 3,3 + 2 + 1,3 + 1 + 1 + 1;
2 + 2 + 2,2 + 2 + 1 + 1,2 + 1 + 1 + 1 + 1; 1 + 1 + 1 + 1 + 1 + 1; 二、整數劃分演算法分析 1、從簡單問題開始入手,對於給定正整數3來說,它可以劃分為:
  • 3;
  • 2 + 1;
  • 1 + 1 + 1;
其劃分的的思想為: 1)將正整數3劃分為其本身,即 3 = 3; 2)將正整數3分割成為僅小於 3 的正整數 2,即3 - 1 = 2,和剩下部分 1,即3 - 2 = 1,所以可以將 3 劃分為 3 = 2 + 1; 3)將第二步分割後中等於1的正整數不再進行劃分,對大於 1 的正整數 2 繼續分割,分割為僅小於 2 的正整數 1,即 2 -1 = 1,和剩下部分 1,即 2 - 1 = 1 ,所以可以將 3 繼續劃分為 3 = 1 + 1 + 1;
2、提升問題規模,對於給定正整數5,它可以劃分為:
  • 6;
  • 5 + 1;
  • 4 + 2,4 + 1 + 1;
  • 3 + 3,3 + 2 + 1,3 + 1 + 1 + 1;
  • 2 + 2 + 2,2 + 2 + 1 + 1,2 + 1 + 1 + 1 + 1;
  • 1 + 1 + 1 + 1 + 1 + 1;
1)將正整數6劃分為其本身,即 6 2)將正整數6劃分為僅小於 6 的正整數 5 即 6 - 1 = 5,和剩下部分 1 即 6 - 5 = 1,所以可以將6劃分為6 = 5 + 1 3)將第二步分割後中等於1的正整數不再進行劃分,對大於 1 的正整數 5繼續分割,分割為僅小於 5 的正整數 4,和剩下部分 2 ,即
6 = 4 + 2 4)將第三步分割後中大於一的最小正整數 2 進行分割,可分割為 2 = 1 + 1,所以可以將6 = 4 + 1 + 1;(注意:每一步僅對大於 1 的最小正整數進行劃分) 5)將正整數6劃分為僅小於 4 的正整數 3 即 6 - 3= 3,和剩下部分 3 即 6 - 3 = 3,所以可以將6劃分為6 = 3 + 3 6)將第五步分割後中大於一的最小正整數 3 進行分割,可分割為僅小於3的正整數 2 和剩下部分 1。即 3 = 2 + 1,所以可以將6劃分為6 = 3 + 2 + 1,對等式右邊的2 又可以劃分為僅小於2的正整數1,和剩下部分1,所以可以將6劃分為6 = 3 + 1 + 1 + 1 7)將正整數6劃分為僅小於 3 的正整數 2 即 4 - 1= 1,和剩下部分 2 以及 另一部分 2 。即可以將6劃分為6 = 2 + 2 + 2 8)將第七步分割後中大於一的最小正整數 2 進行分割,由於第七步劃分後的等式有 3 個 2,所以一次將 3 個 2 劃分為 1 + 1,故可以將6劃分為:6 = 2 + 2 + 1 + 16 = 2 + 1 + 1 + 1 + 1 9)將第八步分割後中大於一的最小正整數 2 進行分割,分割後為2 = 1 + 1,所以可以將6劃分為:6 = 1 + 1 + 1 + 1 + 1 + 1 三、歸納總結 在正整數 n 的所有不同的劃分中,將最大加數 n1 不大於 m 的劃分個數記作q(n,m)。可以建立q(n,m)的如下遞迴關係。 1)q(n,1) = 1,n > = 1 。 當最大加數 n1 不大於 1 時,任何正整數 n 只有一種劃分形式,即 n = 1 + 1 + … + 1(共 n 個1)。 2)q(n,m)= q(n,n),m >= n; 最大加數 n1 實際上不能大於 n 。因此,q(1,m) = 1; 3)q(n,n)= 1 + q(n,n - 1)。 正整數 n 的劃分由 n1 = n 的劃分和 n1 <= n - 1的劃分組成 。 4)q(n,m)= q(n,m - 1)+q(n - m,m - 1),n > m > 1。 正整數 n 的最大加數 n1 不大於 m 的劃分有 n1 = m 的劃分和n1 <= m - 1的劃分組成。 四、JAVA程式碼實現
public class IntegerDivide {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		//分別用正整數3和正整數6進行用例測試
		
		int num1 = 3;
		int num2 = 6;
		
		System.out.println("整數3的劃分數為 : " + dividePrintln(3));
		System.out.println("整數6的劃分數為 : " + dividePrintln(6));
	}
	
	public static int integerDivide(int n, int m){
		
		// n 和 m 為非正整數  返回0
		if(n < 1 || m < 1) {
			
			return 0;
		
		} else if(m == 1 || n == 1){        //對應情況為:q(n,1) = 1,n > = 1,q(1,m) = 1
			
			return 1;
			
		} else if(m > n){		        //對應情況為:q(n,m)= q(n,n),m  >=  n;
			
			return integerDivide(n, n);
			
		} else if(n == m){	    		//對應情況為:q(n,n)= 1 + q(n,n - 1)
			
			return 1 + integerDivide(n, n - 1);
			
		} else {				  //對應情況為:q(n,m)= q(n,m - 1)+q(n - m,m - 1)
			
			return integerDivide(n, m - 1) + integerDivide(n - m, m);
			
		}
		
	}
	
        //中間函式,對給定需要進行劃分的正整數呼叫integerDivide函式。
	public static int dividePrintln(int num){	

		return integerDivide(num,num);
	}

}