算法题思考--1(动态规划,因数)
1.问题背景
本文仅为个人学习记录,有错误请帮我指出,感谢!
题目:一个自然数可以分解成若干个自然数相乘,对于指定自然数n,请求出每种分解自然数之和最小的一个
2.思路
对于一个自然数n,我们发现只要完全分解成一堆质数相乘,就可以使得这些因数的和达到最小。简单证明,
假设a=bc。其中b,c>=2。 ( 此处显然分解成1无意义,会使和更大 ) 则a>=2max{b,c}>=c+b , 由此可见a因数分解后的和比a小。显然a的完全因数分解之后的和最小。
2.1 动态规划思路
定义状态
设 dp[i] 表示将自然数 i 分解为若干个自然数相乘后,这些自然数的最小和。
初始条件
dp[1] = 0,因为1无法分解为多个自然数的乘积。- 对于质数
p,dp[p] = p,因为质数只能分解为自身。
状态转移方程
对于每个 i,我们尝试将其分解为两个数 j 和 k(即 i = j × k),然后更新 dp[i]:
dp[i] = min(dp[i], dp[j] + dp[k])
3.代码实现
import java.util.Arrays;
public class MinSumFactorization {
public static int minSumFactorization(int n) {
// dp[i] 表示将 i 分解为若干个自然数相乘后的最小和
int[] dp = new int[n + 1];
Arrays.fill(dp, Integer.MAX_VALUE); // 初始化为最大值
dp[1] = 0; // 1 无法分解,和为 0
// 填充 dp 数组
for (int i = 2; i <= n; i++) {
// 考虑 i 本身作为一个因子
dp[i] = Math.min(dp[i], i);
// 尝试将 i 分解为 j * k
for (int j = 2; j * j <= i; j++) {
if (i % j == 0) {
int k = i / j;
dp[i] = Math.min(dp[i], dp[j] + dp[k]);
}
}
}
return dp[n];
}
public static void main(String[] args) {
int n = 12;
System.out.println("最小和为: " + minSumFactorization(n)); // 输出 7
}
}
4.因数分解
5.参考资料
判断 N 是否是质数,为什么判断到根号 N 就可以了? - 刘明的回答 - 知乎