0002演算法--------整數劃分問題演算法分析及JAVA程式碼完美實現
阿新 • • 發佈:2019-01-07
整數劃分演算法分析以及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來說,它可以劃分為:
2、提升問題規模,對於給定正整數5,它可以劃分為:
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 + 1,6
= 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程式碼實現
- 3;
- 2 + 1;
- 1 + 1 + 1;
- 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;
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);
}
}