研习代码 day35 | 初始动态规划——整数拆分 && 不同的二叉搜索树

 一、整数拆分

        1.1 题目

        给定一个正整数 n ,将其拆分为 k 个 正整数 的和( k >= 2 ),并使这些整数的乘积最大化。

        返回 你可以获得的最大乘积 。

示例 1:

输入: n = 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1。

示例 2:

输入: n = 10
输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。

提示:

  • 2 <= n <= 58

        1.2 题目链接

        343.整数拆分

        1.3 解题思路和过程想法

        (1)解题思路

        总体思路:将一个整数拆成两个数(其内部可再进行拆分),由递推求得其组成的最大积。
        # dp[i] 表示 i 经过拆分后,能得到的最大乘积
        # 递推关系:max(拆成其他元素后最大乘积,拆成两个元素的乘积,第一个元素*拆第二个元素的乘积)——dp[i] = max(dp[i], i * (i-j) , i * dp[i-j])
        # 注:为什么不拆第一个元素,因为拆第一个元素(大元素)的情况已经包括在之前的拆小元素中了
        # 从前往后遍历,将 i 拆分为 j + i-j
        # 优化:因为10=1+9,10=9+1 是重复的,所以 j 只需遍历一半元素即可

        (2)过程想法

       最初对递推关系式没有思路

        1.4 代码

class Solution:
    def integerBreak(self, n: int) -> int:        
        # dp[i] 表示 i 经过拆分后,能得到的最大乘积
        dp = [0] * (n+1)

        # 递推关系:max(拆成其他元素后最大乘积,拆成两个元素的乘积,第一个元素*拆第二个元素的乘积)
        # dp[i] = max(dp[i], i * (i-j) , i * dp[i-j])
        # 注:为什么不拆第一个元素,因为拆第一个元素(大元素)的情况已经包括在之前的拆小元素中了

        # 初始化
        dp[2] = 1

        # 从前往后遍历,将 i 拆分为 j + i-j
        # 优化:因为10=1+9,10=9+1 是重复的,所以 j 只需遍历一半元素即可
        for i in range(3,n+1):
            for j in range(1,i//2+1):
                dp[i] = max(dp[i], j * (i-j), j * dp[i-j])

        return dp[n]

二、不同的二叉搜索树

        2.1 题目

        给你一个整数 n ,求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种?返回满足题意的二叉搜索树的种数。

示例 1:

输入:n = 3
输出:5

示例 2:

输入:n = 1
输出:1

提示:

  • 1 <= n <= 19

        2.2 题目链接

        96.不同的二叉搜索树

        2.3 解题思路和过程想法

        (1)解题思路

        # 数组:i 个节点组成的二叉搜索树的种数 dp[i]
        # 递推关系:
         dp[i] = \sum_{0}^{i}dp[j-1]*dp[i-j]
        # 以 j 节点为头结点 += 左子树为 j-1 个节点的搜索树 * 右子树为 i-j 个节点的搜索树
        # d[3] = dp[0]*dp[2] + dp[1]*dp[1] + dp[2]dp[0]
        # dp[3] = 以 1 为头节点的情况+以 2 为头节点的情况+以 3 为头节点的情况

        (2)过程想法

        最初没有具体的想法,没想着遍历所有不同头节点的二叉搜索树

        2.4 代码

class Solution:
    def numTrees(self, n: int) -> int:
        # 数组:i 个节点组成的二叉搜索树的种数 dp[i]
        dp = [0] * (n+1)

        # 递推关系:以 j 节点为头结点 += 左子树为 j-1 个节点的搜索树 * 右子树为 i-j 个节点的搜索树
        # dp[i] += dp[j-1] * dp[i-j]
        # d[3] = dp[0]*dp[2] + dp[1]*dp[1] + dp[2]dp[0]
        # dp[3] = 以 1 为头节点的情况+以 2 为头节点的情况+以 3 为头节点的情况

        # 初始化
        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]  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值