整数拆分
给定一个正数n,求n的裂开方法数,
规定:后面的数不能比前面的数小
比如4的裂开方法有:
1+1+1+1、1+1+2、1+3、2+2、4 5种,
所以返回5
暴力递归
根据题目要求,后面的数不能比前面的数小 …
所以递归时,要有变量记录前面拆分的值.
还有知道剩余多少值,才能确定怎么拆分.
这样递归的参数就定好了.下面就是不断递归尝试了.
代码演示
/**
* 计算拆分方案
* @param n
* @return
*/
public static int ways(int n) {
if (n < 0){
return 0;
}
if (n == 1){
return 1;
}
return process(1,n);
}
/**
* 暴力递归
* @param pre 前面拆分的数
* @param next 还剩余的数
* @return
*/
public static int process(int pre,int next){
//base case 剩余0 时,前面拆分方案有效,返回1
if (next == 0){
return 1;
}
// 违反题目规定,无效方案 返回 0
if (pre > next){
return 0;
}
int ways = 0;
//递归
for (int i = pre; i <= next;i++){
ways += process(i,next - i);
}
return ways;
}
动态规划
直接改写递归,比较简单 直接上代码了:
/**
* 动态规划
* @param n
* @return
*/
public static int dp1(int n){
if (n == 1){
return 1;
}
int[][]dp = new int[n + 1][n + 1];
for (int i = 1;i <= n;i++){
dp[i][0] = 1;
dp[i][i] = 1;
}
for (int pre = n - 1; pre >= 1;pre--){
for (int rest = pre + 1;rest <= n;rest++){
int ways = 0;
for (int i = pre; i <= rest;i++){
ways += dp[i][rest - i];
}
dp[pre][rest] = ways;
}
}
return dp[1][n];
}