代码随想录第41天|343. 整数拆分、96.不同的二叉搜索树

56 阅读1分钟

343. 整数拆分

1. first idea

dp[i]表示正整数i的拆分后的最大乘积。

dp[i]=max(dp[j]×dp[ij],j[1,i//2])dp[i]=max(dp[j]\times dp[i-j], j\in[1,i//2])

计算时我意识到 dp[4]=2×2dp[4]=2\times 2而不是dp[4]=dp[2]×dp[2]=1×1dp[4]=dp[2]\times dp[2]=1\times 1.

所以我们其实要做比较

dp[i]=max(max(dp[j]×dp[ij],j×(ij)),j[1,i//2])dp[i]=max(max(dp[j]\times dp[i-j], j \times (i -j)), j\in[1,i//2])

但是这样仍然是有问题的,比如8=2×3×38=2\times 3\times 3。 这个不符合上述两种情况的任何一种,

它既不满足dp[2]×dp[6]dp[2]\times dp[6]也不满足2×62\times 6,而是2×dp[6]2\times dp[6].

所以我们的内层maxmax操作并不是这两种情况的比较,

而是max(dp[j],j)×max(dp[ij],ij)max(dp[j],j)\times max(dp[i-j], i-j).

class Solution:
    def integerBreak(self, n: int) -> int:
        dp = [0] * (n + 1)
        dp[1] = 1
        dp[2] = 1
        for idx in range(3, n + 1):
            max_dp = max(dp[1] * dp[idx - 1], 1 * (idx - 1))
            for j in range(1, (n // 2) + 1):
                if max_dp < (max(dp[j], j) * max(dp[idx - j], idx - j)):
                    max_dp = max(dp[j], j) * max(dp[idx - j], idx - j)
            dp[idx] = max_dp
        # print(dp)
        return dp[-1]

96. 不同的二叉搜索树

1. first idea

dp[i]表示有i个节点时,能构建多少种二叉树。

但是怎么通过前置结果推这个结果我还不确定。

2. doc reading

代码随想录 (programmercarl.com)

1~(j-1)号节点构成左子树;

(j+1)~i号节点构成右子树。

dp[i]=j=1idp[j1]×dp[ij]dp[i]= \sum_{j=1}^i dp[j-1] \times dp[i - j]

初始化:

dp[0]=1,dp[1]=dp[0]×dp[0]=1,dp[2]=dp[0]×dp[1]+dp[1]×dp[0]=2dp[0]=1, dp[1]=dp[0]\times dp[0]=1, dp[2]=dp[0]\times dp[1]+dp[1]\times dp[0]=2

class Solution:
    def numTrees(self, n: int) -> int:
        dp = [0] * (n + 1)
        dp[0] = 1
        for idx in range(1, n + 1):
            for root_idx in range(1, idx + 1):
                dp[idx] += dp[root_idx - 1] * dp[idx - root_idx]
        return dp[-1]