343. 整数拆分
思路
- dp[i]: 分拆数字i,可以得到的最大乘积为dp[i]。
- 要把i分解成多个数的和再将它们相乘,我们从1遍历到i为止,把每个遍历到的j值,作为单个因子,把剩余的总和(i-j)分解。分解有两种,一种是(i-j)单位单个因子,也就是把i直接分解成j和(i-j)的乘积。另一种是把(i-j)表示为多个数的乘积,得到最大乘积,(i-j)所分拆得到的乘积肯定越大越好,而根据dp[i]的定义,dp[i-j]就是最大乘积,所以i又可分解成dp[i-j]和i的乘积,我们想要这两种方法种最大的结果,又因为对于每个j,都要计算得到一个dp[i], 我们还需把dp[i]加入到比较当中,相当于不断更新dp[i]的值,取最大的。最终推导公式为:dp[i] = max(dp[i], j(i-j), j*dp[i-j])
- dp[i]依赖于dp[i-j],因此从前往后遍历。
- 初始值:dp[2] = 1
代码实现
class Solution(object):
def integerBreak(self, n):
dp = [0]*(n+1)
dp[2] = 1
for i in range(3, n+1):
for j in range(1, i//2+1):
dp[i] = max(dp[i], (i-j)*j, dp[i-j]*j)
return dp[n]
96. 不同的二叉搜索树
题目链接:96. 不同的二叉搜索树 - 力扣(LeetCode)
思路
对于1-n个节点组成的二叉搜索树,根节点可以是1-n总共n种,每一种根节点的数量是以此为根结点左子树节点数量和以此为根节点右子树的数量的乘积。
- dp[i] : 1到i为节点组成的二叉搜索树的个数为dp[i]
- dp[i] += dp[j - 1] * dp[i - j]; ,j-1 为j为头结点左子树节点数量,i-j 为以j为头结点右子树节点数量
- dp[0] = 1
- 递推公式表明节点数为i的状态是依靠 i之前节点数的状态。
代码实现
class Solution(object):
def numTrees(self, n):
dp = [0]*(n+1)
dp[0] = 1
for i in range(1, n+1):
for j in range(1, i+1):
dp[i] += dp[j-1] * dp[i-j]
return dp[n]