遞歸案例-正整數劃分

如果你對其他算法或者案例感興趣,請考慮閱讀我的以下文章。

遞歸案例-漢諾塔.
遞歸案例-全排列.
動態規劃案例-矩陣連乘(含表格填寫、問題理解、實例解決).
動態規劃案例-最長公共子序列(含表格填寫、問題理解、實例解決、例題答案).
遞歸案例-電路佈線(含表格填寫等超詳細,純人話講解).


通過對網上一些大神博主的文章的學習,加上自己的理解,簡單解決一下這個案例。

問題

將正整數n表示成一系列正整數之和: n=n1+n2+…+nk, 其中n1≥n2≥…≥nk≥1,k≥1。正整數n的這種表示稱爲正整數n的劃分。求正整數n的不同劃分個數。
對於這個問題,我們可以通過一個例子來理解它。
eg:正整數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

問題分析

爲什麼要用遞歸

遞歸的定義:函數調用自身。
我認爲運用遞歸的條件就是:每一步進行的操作基本相同,並且問題規模逐漸減小。
通過上面的例子,我們可以看出,6的劃分個數=以5爲界限對6劃分的個數+(6),每一個子問題的操作基本相同,並且問題規模在不斷減小。

函數理解

我們可以用p(n,m)來表示以m爲界限(劃分的數不能超過m)對n進行劃分的個數
有點難理解?
舉個例子
p(6,3)=
(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)
=7

情況分析

對於實際情況我們可能會遇到以下的情況:
1.m>n p(n,m) 理解:以m爲界限對n進行劃分,這種情況也就等於p(n,n)。例如以6爲界限和以7爲界限對6所得到的劃分都是一樣的。
eg:p(6,7)=p(6,6)。
2. n =1 p(1,m) 理解:以m爲界限對1進行劃分,那麼這種情況只有一種,也就是1。eg:p(1,2)=p(1,1)=1。
3.m=1 p(n,1) 理解:以1爲界限對n進行劃分,那麼這種情況也只有一種,也是1。
eg:p(3,1) = (1+1+1)=1。
4.m=n p(n,n) 理解:以n爲界限對n進行劃分。這種情況下它等於p(n,n-1)+1。
eg:p(6,6) = (6) + p(6,5)
5.m<n p(n,m) 理解:以m爲界限對n進行劃分。這種情況下它等於p(n,m-1)+p(n-m,m)1。這個比較難理解。他可以理解爲以m爲界限對n的劃分=以m-1爲界限對n的劃分+含m時對n的劃分

eg:p(6,3)=p(n,m-1)+p(n-m,m)
=p(6,2)+p(3,3)
={ (2+2+2),(2+2+1+1),(2+1+1+1+1),(1+1+1+1+1+1) }+{ (3+3),(3+2+1),(3+1+1+1) }

代碼演示

通過對不同情況的分析,我們寫出遞歸函數。
遞歸函數代碼:

public static int p(int n,int m)
 {
  if(n<=0)
   return 0;
  else if(n==1||m==1)
   return 1;
  else if(m>n)
   return p(n, n);
  else if(m==n)
   return 1+p(n, n-1);
  else
   return p(n, m-1)+p(n-m,m);
  
 }

主函數代碼:

 public static void main(String[] args) {
  System.out.println("6的整數劃分有"+p(6, 6)+"種");
  
 }

輸出結果

在這裏插入圖片描述


  1. 用p(n-m,m)來表示是因爲:劃分中已經包含了m,所以只需要劃分n-m的數據。例如,p(6-4,4)這個劃分中第一個數爲4,以4爲劃分第一個數繼續劃分。
    第二個參數有些玄學,個人理解不深:
    在比較 n-m和m的大小的時候,產生了一個很有意思的現象:
    當n-m>m的時候,由於我們要保證最大值是6,所以我們必須得給他的劃分設置一個界限而這個界限的大小就是m
    當n-m<m的時候,我們不用考慮界限的選取,因爲假如界限選的很大都會成爲第一種情況而導致界限變成n-m ↩︎

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