整数划分的三种解法

整数划分的三种解法

  • 1、递归
  • 2、完全背包
  • 3、dp

题目描述:

对于一个整数n 来说可以表示为n = n1 + n2 +
n3 + … + nk 其中n1 >= n2 >= n2 … >= 1
求解n 有多少种划分方法

1、递归

如果n 是4, 可以分为:

4 = 4
4 = 3 + 1
4 = 2 + 2
4 = 2 + 1 + 1
4 = 1 + 1 + 1 + 1

总共5中划分方法,观察上面的等式,可以发现每次都有一个最大的ni 比如4 = 3 + 1, 最大的ni = 3
所以可以定义一个函数f(n, m) 表示最大的ni 不超过m 的划分方法个数
那么最后的答案就是f(n, n)
不是一般性考虑对于任意的f(n, m) 如何转化

1· 如果m > n 由于ni 不会大于n 所以 f(n, m) = f(n, n)
2· 如果n == m, 当ni = n 的时候划分集合只有{n} 这时候可以将ni 单独拿出,f(n, n) = 1 + f(n, n - 1)
3· 当m < n 时, 若ni = m,可以划分为{m, {n1, n2 … nk}} 这么一种集合,sum{n1, n2 … nk} = n - m这时候f(n, m) = (n - m, m)
若ni != m,可以划分为{n1, n2, … nk} 集合,这时候f(n, m) = f(n, m - 1)
4· 当n == 1 || m == 1 只有一种方案 {1, 1, 1,…,1}

所以代码为:

int f(int n, int m) {if(n <= 0 || m <= 0) return 0;if(n == 1 || m == 1) return 1;if(m > n) return f(n, n);if(m == n) return f(n, m - 1) + 1;return f(n, m - 1) + f(n - m, m);
}

2、完全背包

观察划分的方式可以发现,这是一种特殊的组合问题,从1 ~ n 中选任意的数使得总和等于n 的方案个数

这样就抽像为经典的完全背包问题

物品为1 ~ n 中间的数,体积为i, 价值为i

定义f(i, j) 表示考虑[1, i] 之间的数,使得总和为j 的方案个数

状态转移:f(i, j) = f(i - 1, j) + f(i - 1, j - i) + f(i - 1, j - 2 * i) + … + f(i - 1, j - k * i)

最后答案就是f(n, n), 初始化f(0, 0) = 1

int get_back(int n) {int[][] f = new int[n + 1][n + 1];f[0][0] = 1; // 初始化for(int i = 1; i <= n; ++i) for(int j = 1;j <= n; ++j ) for(int k = 0;k * i <= j; ++k)f[i][j] += f[i - 1][j - k * i];return f[n][n];
}

时间复杂度:O(n3) ,可以优化为O(n2)这里就不介绍了

3、dp

除了用背包的思想还可以将划分的集合分类,用dp

  1. 划分集合的最小值是1
  2. 划分集合最小值不是1

可以定义dp[i][j] 表示 考虑正好有i 个数使得和为j 的方案数
那么如果最小值为1,可以去掉最后一个1,dp[i][j] = dp[i - 1][j - 1]

如果最小值不是1 可以将集合所有元素都减去1, 总共可以减去i 个1 所以dp[i][j] = dp[i][j - i]

状态转移:dp[i][j] = dp[i - 1][j - 1] + dp[i][j - i]

因此代码为:

int get_dp(int n) {int[][] dp = new int[n + 1][n + 1];// 初始化 dp[1][i] 集合只有一种可能 {i}for(int i = 1;i <= n; ++i ) dp[1][i] = 1;for(int i = 2;i <= n; ++i )for(int j = i;j <= n; ++j)dp[i][j] = dp[i - 1][j - 1]  + dp[i - 1][j - i];// 最后统计所有的dp[i][n] 就可以int res = 0;for(int i = 1;i <= n; ++i) res += dp[i][n];return res;}

时间复杂度:O(n2)


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部