2020.7.30 力扣每日
1 class Solution { 2 public int integerBreak(int n) { 3 int[] dp = new int[n + 1]; //动态数组 4 for (int i = 2; i <= n; i++) { 5 for (int j = 1; j < i; j++) { //对于dp[i]来说,最大乘积为两种可能,1、将i拆分为j与i-j,2、将i-j继续拆分,则用dp[i-1]表示 6 dp[i] = Math.max(dp[i], Math.max(j * (i - j), j * dp[i - j])); 7 } 8 } 9 return dp[n]; 10 } 11 }
解题思路:
题目要求拆分正整数n,求最大乘积。对于此类,将xxx拆分成xxx,求xxx的最优解,一般都可用动态规划解决。此题也是如此,分析题目,发现拆分过程中,要么将n拆分为两部分,j与n-j;要么,将其继续拆分,而继续拆分的过程中,由于j是可变的,也就是j能模拟拆分结果中的任意部分,那么我们继续拆分时,就相当于,拆分n-j,使乘积更大,而这个操作又等价于将n-j看成一个新的整体,求其拆分的乘积的最大值。而这就是动态规划的思想了。
所以我们可以使用dp[n]表示拆分n时的解,那么继续拆分,就相当于求dp[n-j]的解。那么对于n来说就是用j遍历[1,n),dp[n] = max(j * (n * j),j * dp[n - j]。最后我们取出dp[n]的最大值就是n时的解了。那么比n小的值的dp值如何求呢?我们只需要,利用i变量,遍历[2,n],将动态方程中的n改为i即可。
注意点:
n是大于等于2的,边界情况dp[0] = dp[1] = 0。并且i需从2开始遍历。
时间复杂度:O(N^2),N为给定的数字大小
空加复杂度:O(N)