代码随想录算法训练营第四十一天| 343. 整数拆分,96. 不同的二叉搜索树
343. 整数拆分
题目链接:整数拆分
这个题一开始要多写几个分析一下:
- n=2 1+1(1)
- n=3 1+1+1(1) 2+1(2)
- n=4 1+1+2(2) 2+1+1(2) 2+2(4)
- n=5 1+1+3(3) 2+1+2(4) 3+2(6)
- n=6 1+1+4(4) 2+1+3(6) 2+2+2(8) 3+2+1(6) 3+3(9)
- n=7 1+1+5(5) 2+1+4(8) 2+2+3(12) 3+2+2(12) 3+3+1(9) 3+4(12)
- n=8 1+1+6(6) 2+1+5(10) 2+2+4(16) 3+2+3(18) 3+3+2(18) 4+4(16)
他不是简单的,直接往后遍历找到最大的那个dp[i-j]*j
- 首先由于k至少是2,所以到n能通过dp产生的都是k>=3的,我们需要自己计算拆成两个的情况,k=2的时候最大的也就是 n / / 2 × ( n − n / / 2 ) n//2 \times (n-n//2) n//2×(n−n//2)。
- 第二点是第二个循环怎么遍历,首先不能从2开始,因为2的最大乘积是1,那么2能推出的dp也只有 n − 2 n-2 n−2而已,而n = n-1+1,dp至少可以有n-1的最大乘积就算只有n-1也比n-2大。
class Solution:
def integerBreak(self, n: int) -> int:
# dp[i] = i+2的乘积最大化
dp = [0] * (n-1)
dp[0] = 1
for i in range(1,(n-1)):
# dp[i] 是i+2的最大乘积,i+2 = i+1+1,所以dp[i]至少是dp[i-1]
# 以及如果k=2,那么最大乘积就是(n//2)*(i+2-n//2)
a = (i+2)//2
dp[i] = max(a*(i+2-a),dp[i-1])
for j in range(1,(i-2)):
dp[i] = max(dp[i],dp[j]*(i-j))
return dp[-1]
96. 不同的二叉搜索树
题目链接:不同的二叉搜索树
解析
确实没想到。
思路是如果是n的不同二叉树,那么以i为root的情况下,左边可以挂元素为1到(i-1)的搜索二叉树,右边可以挂(i+1)到n的索索二叉树,(i+1)到n的搜索二叉树种类和n-i的搜索二叉树种类是一样的,所以每次遍历加上一个dp[n-i]*dp[i-1]就可以。
class Solution:
def numTrees(self, n: int) -> int:
dp = [0] * (n + 1)
dp[0], dp[1] = 1, 1
for i in range(2, n + 1):
for j in range(1, i + 1):
dp[i] += dp[j - 1] * dp[i - j]
return dp[-1]