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)

posted @ 2020-07-30 22:48  小小码农-安  阅读(165)  评论(0编辑  收藏  举报