这几天有在开始投暑期实习的简历,可能确实是投的太晚了,好多厂都没有hc了,阿里简历面都没过(感觉是kpi面试),被深深打击到了呜呜呜,花了两天整理情绪,重新出发,下篇文章针对阿里简历面的问题进行重新整理。
很久没有刷题了,今天遇到一个动态规划的问题,代码随想录讲的不是很清晰,然后我看了下网上的解释,结合代码随想录的知识重新进行了整理;
首先先看题目:
其实动态规划的问题,其实就是把一个问题拆解成若干个子问题,先解决子问题,然后从这些子问题出发得到原问题的解。
针对上面这个问题,我们现在已经拿到正整数n
,当n
大于等于2的时候可以拆成至少两个正整数的和。令x
是拆分出的第一个正整数(取值范围在1~(n-1)
),那么剩下的部分就是n-x
;
n-x
有两种情况:
- 不可以继续拆分,那么乘积就是
x*(n-x)
; - 可以继续拆分成至少两个正整数的和,那么乘积就是
x*(n-x)
的乘积最大化,将子问题求得解即2到n的所有乘积最大化
存入数组dp[n]
中,那么乘积就是x*dp[n-x]
;
其实光看上面这段话还是很难让人理解:
简单来说,就是我们自己创建一个数组dp,i表示从1到n的数字,dp[i]表示分解数字i可以得到的最大乘积,其实这就是一个迭代递归的过程,那么我们可以知道dp[0]和dp[1]是没有初始值的,因为0和1不可以拆分,所以我们可以从dp[2]开始设置初始值,dp[2]=1(因为2=1+1),那么接下来就应该从i=3开始遍历。
怎么确定递推公式呢?
我们从1到n开始遍历,每次遍历i,我们都要计算dp[i]的值,就相当于去遍历里再套一个遍历j,遍历1到i-1的值,然后取拆分中的乘积最大的情况,这里存在两种情况,一种是对i拆分成两个数,那么dp[i]=(i-j)*j
;第二种是对i进行拆分成多个数,那么dp[i]=dp[i-j]*j
然后取最大的值就好啦(确实这个题不太好理解,可能要看好几遍才能真的理解,如果看了好几遍文字依旧是一知半解,可以对照着代码一起看)
/**
* @param {number} n
* @return {number}
*/
var integerBreak = function(n) {
var dp=Array(n+1).fill(0);
dp[2]=1;
for(var i=3;i<=n;i++){
for(var j=1;j<i-1;j++){
dp[i]=Math.max(dp[i],Math.max((i-j)*j,dp[i-j]*j));
}
}
return dp[n];
};