代码随想录第四十一天 | 整数拆分&&不同的二叉搜索树
343.整数拆分
文章:8. 整数拆分
题目:343. 整数拆分
【思路】
将凑成整数的和,凑出最大的乘积。
1.确定dp[i]及其下标
dp[i] : 拆分数字i,得到的最大乘积dp[i]
2.确定递推公式
dp[i]是如何获得的?
dp[i] 可以 j *(i-j) 、dp[i-1]+1获得。
因此从二者中取最大值即可。
dp[i] = max(j*(i-j) , dp[i-j] *j)
同时,因为i和j 会变化,会重复计算dp[i],因此我们还需要对dp[i]进行比较
-> dp[i] = max(dp[i],max(dp[i-j]*j, j * (i-j)))
3.数组初始化
dp[2] = 1
4.确定遍历顺序
因为dp[i]依靠dp[i-j]的状态,所以遍历顺序一定是从前向后的。
5.举例推导
。。。。
- Java实现
1 | class Solution { |
- Go实现
1 | func integerBreak(n int) int { |
96.不同的二叉搜索树
文章:9. 不同的二叉搜索树
题目:96. 不同的二叉搜索树
【思路】
dp[3],就是元素1为头结点搜索树的数量+元素2为头结点搜索树的数量+元素3为头结点搜索树的数量。
元素1为头结点搜索树的数量 = 右子树有2个元素的搜索树数量 * 左子树有0个元素的搜索树数量。
元素2为头结点搜索树的数量 = 右子树有1个元素的搜索树数量 * 左子树有1个元素的搜索树数量。
元素3为头结点搜索树的数量 = 右子树有0个元素的搜索树数量 * 左子树有2个元素的搜索树数量。
所以dp[3] = dp[2]*dp[0] + dp[1] * dp[1] + dp[0] *dp[2]
1.确定数组dp[i]及其下标的含义
dp[i] : 1到i为节点组成的二叉搜索树的个数为dp[i](i个不同元素节点组成的二叉搜索树的个数为dp[i])
2.确定递推公式
dp[i] += dp[以j为头结点左子树节点数] * dp[以j为头结点右子树节点数量]
j相当于是头结点的元素,从1遍历到i为止
-> dp[i] += dp[j-1] * dp[i-j] ,j-1为以j为头结点的右子树结点数、i-j为以j为头结点的右子树节点数量
3.初始化数组
dp[0] 应该是多少?
从定义上来说,空节点也是一棵二叉树,也是一棵二叉搜索树;从乘法来说也需要dp[0]为1,不然0*任何数都为0
4.确定遍历顺序
dp[i]是依靠i之前的节点数的,因此需要遍历i里面的每一个数作为头结点的状态。
5.举例推导
…
- Java实现
1 | class Solution { |
- Go实现
1 | func numTrees(n int) int { |
【算法总结】
整数拆分:需要**将dp[i]拆成dp[i-j]*j 和 j *(i-j)取最大值,并且由于dp[i]会不断更新,因此也需要比较dp[i]和以上最大值**,取两者真正的最大值。
不同的二叉搜索树:头结点为n的二叉树实质是左右子树为由前n项的二叉树累加组成,*dp[i] += dp[i-j]dp[j-1]