开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 10 天,点击查看活动详情
前言
算法的重要性不言而喻!区分度高!
现在学习的门槛低了,只有能上网每个人都可以学编程!培训班6个月就可以培养出来能干活的人,你怎么从这些人中脱颖而出?没错!就是学算法,学一些底层和基础的东西。
说的功利点是为了竞争,卷死对手。真心话说就是能提高自己的基础能力,为技术可持续发展做好充分的准备!!!
提前入门学习书籍:CPrimerPlus、大话数据结构
刷题网站
我是按照代码随想录提供的刷题顺序进行刷题的,大家也可以去刷leetcode最热200道,都可以
刷题嘛,最重要的就是坚持了!!!
画图软件
OneNote
这个要经常用,遇见不懂的流程的话就拿它画一画!
笔记软件
Typoral
题目
解析
当一个问题有很多重叠的子问题,每一个状态都是由上一个状态推导出来的,使用DP是最有效的!
这题直接就是看题解,看到别人用数学公式推导得出
① 当所有拆分出的数字相等时,乘积最大。
② 最优拆分数字为 3。
我们就不用去证明了,直接拿来用。原文链接为:343. 整数拆分(数学推导,清晰图解) - 整数拆分 - 力扣(LeetCode)
我们需要学会用DP去解决这个问题
动态规划解题套路
- 确定dp数组以及下标的含义
dp[i]:拆分数字i,dp[i]为最大乘积
后面我们要贯彻这个思想,如果忘了就来想一下,dp[i]表示拆分数字i的最大乘积
- 确定递推公式
前面解析我们知道,想要获得最大乘积有两种方式:
- 当所有拆分出的数字相等时,乘积最大。
- 最优拆分数字为 3。
那么递推公式(状态转移方程)该怎么写呢?
- 我们可以让j从1开始遍历,然后就能得到
dp[i] = j * (i - j) - 一个是
dp[i] = j * dp[i-j]
所以递推公式为:
dp[i] = Math.max(dp[i],Math.max(i*(i-j),i*dp[i-j]))
dp[i-j]什么意思???
想一下dp[i]的定义,dp[i]表示拆分数字i的最大乘积
那么dp[i-j],dp[i-j]表示拆分数字i-j的最大乘积
举例说明:i = 10,j = 1求整数拆分后的最大乘积
dp[i] = j * (i - j)--> 10 = 1 + 9 --> 1 * (10 -1) = 9dp[i] = j * dp[i-j]--> 10 = 1 + 1 + 8 --> 1 * 1 * 8 = 8
当 j = 2 时,推导如下:
dp[i] = j * (i - j)--> 10 = 2 + 8 --> 2 * (10 -2) = 16dp[i] = j * dp[i-j]--> 10 = 2 + 2 + 6 --> 2 * 2 * 6 = 24
当 j = 3 时,推导如下:
dp[i] = j * (i - j)--> 10 = 3 + 7 --> 3 * (10 -3) = 21dp[i] = j * dp[i-j]--> 10 = 3 + 3 + 4 --> 3 * 3 * 4 = 36
...
- dp数组如何初始化
dp[0]和dp[1]怎么定义呢?它们怎么拆分呢?我们不定义,我们直接定义dp[2]
dp[2] = 1
- 确定遍历顺序
dp[i]的状态依赖dp[i-j]所以肯定是从前向后遍历
至于j枚举的时候,我们可以做一点优化,j <= i / 2,因为j大于i / 2 的话其实就是重复计算
- 举例推导dp数组
dp[i] = j * (i - j)--> 10 = 1 + 9 --> 1 * (10 -1) = 9dp[i] = j * dp[i-j]--> 10 = 1 + 1 + 8 --> 1 * 1 * 8 = 8
当 j = 2 时,推导如下:
dp[i] = j * (i - j)--> 10 = 2 + 8 --> 2 * (10 -2) = 16dp[i] = j * dp[i-j]--> 10 = 2 + 2 + 6 --> 2 * 2 * 6 = 24
当 j = 3 时,推导如下:
dp[i] = j * (i - j)--> 10 = 3 + 7 --> 3 * (10 -3) = 21dp[i] = j * dp[i-j]--> 10 = 3 + 3 + 4 --> 3 * 3 * 4 = 36
...
是不是非常的神奇呢?
第一次写要多理解DP的套路,然后多练习就可以了!
完整代码
看不懂?没办法,多写多练多总结!
还是带入代码到示例中多去总结多练习!
class Solution {
public int integerBreak(int n) {
int[] dp = new int[n+1];
dp[2] = 1;
for(int i = 3;i<=n;i++){
for(int j = 1;j<= i-j;j++){
dp[i] = Math.max(dp[i],Math.max(j * (i-j),j*dp[i-j]));
}
}
return dp[n];
}
}