整數劃分問題及其算法
一、問題描述
整數劃分問題是將一個正整數n拆成一組數連加並等於n的形式,且這組數中的最大加數不大於n。
如整數的6劃分爲:
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共11種。
二、算法描述
下面通過遞歸方法得到一個正整數的劃分數。
遞歸函數的聲明爲 int split(int n, int m);其中n爲要劃分的正整數,m是劃分中的最大加數(當m > n時,最大加數爲n),
Ⅰ.當n = 1或m = 1時,split的值爲1,可根據上例看出,只有一個劃分1 或 1 + 1 + 1 + 1 + 1 + 1
可用程序表示爲if(n == 1 || m == 1) return 1;
Ⅱ.下面看一看m 和 n的關係。它們有三種關係
(1) m > n
在整數劃分中實際上最大加數不能大於n,因此在這種情況可以等價爲split(n, n);
可用程序表示爲if(m > n) return split(n, n);
(2) m = n
這種情況可用遞歸表示爲split(n, m - 1) + 1,從以上例子中可以看出,就是最大加數爲6和小於6的劃分之和
可用程序表示爲if(m == n) return (split(n, m - 1) + 1);
(3) m < n
這是最一般的情況,在劃分的大多數時都是這種情況。從上例可以看出,設m = 4,那split(6, 4)的值是最大加數小於4劃分數和整數2的劃分數的和。
可用程序表示爲split(n, m - 1) + split(n - m, m)
三、程序語言實現
因爲算法是程序的核心部分,而算法是一致的,所以下面的程序思路一致,大同小異,只是形式不一而已。
1.Java實現:
2.C++實現:
C++實現的比較潦草,沒有讓用戶輸入數據,沒有一般交互性,不過可以自己再改正一下!
就遞歸方式而言,最大的不好之處就是遞歸次數太多,做了太多的冗餘計算。
(N,M) 所需時間(ms)
100,100 250
120,120 1281.3
140,140 6297
160,160 27484.7
180,180 110844.5
200,200 398417.4
相對而言,動態規劃效率要高很多,不是一個數量級的,篇在介紹啊!