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


    参考

    代码随想录

    题目一:LeetCode 343.整数拆分

    1. 确定dp数组及其下标的含义
      dp[i]为整数i拆分后得到的最大化乘积。
    2. 确定递推公式
      dp[i]可以有两种方式得到:
    • dp[i] = j * (i-j),即只拆分成两个数,其中1 <= j <= i/2,最终dp[i]应该是所有j取值得到dp[i]中的最大值
    • dp[i] = j * dp[i-j],这种情况相当于将整数i拆分成多个数,因为其中的dp[i-j]已经被拆分过了,至少被拆分成两个数,具体拆分成多少个数不用去管,其中1 <= j <= i/2,同样dp[i]也是所有取值中的最大值。

    在具体的代码实现上,dp[i] = max(dp[i],j * (i - j),j * dp[i - j]),这样对于每个i,只需要遍历一遍j就可以得到dp[i]了。把dp[i]放到max函数中的目的就是不断更新最大值。

    1. 初始化dp数组
      i = 0或1时,dp[i]是用不到的,所以不需要初始化只需要将dp[2]初始化为1,即dp[2] = 1

    2. 确定遍历顺序
      对于i,dp[i]需要由dp[i-j]来确定,所以i应该从小到大遍历;对于j,既可以从大到小也可以从小到大。

    3. 举例推导dp数组
      以n = 10为例,根据下面的递推公式进行推导:

    dp[i] = max(dp[i],j * (i - j),j * dp[i - j]),其中3 <= i <= 10,1 <= j <= i/2
    
    • 1

    推导得到的dp数组为[1,2,4,6,9,12,18,27,36](注意下标从2开始),因此dp[10] = 36。

    具体的代码实现如下:

    class Solution {
    public:
        int integerBreak(int n) {
            vector<int> dp(n+1);
            dp[2] = 1;
            for(int i = 3; i <= n; i++)
                for(int j = 1; j <= i/2; j++)
                    dp[i] = max(dp[i], max(j * (i - j), j * dp[i - j]));
            return dp[n];
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    题目二:LeetCode 96.不同的二叉搜索树

    在这里插入图片描述
    在这里插入图片描述
    感觉这个题更像是找规律的题目,但是这个规律很难看出来。
    dp[3]就是元素1为头结点搜索树的数量 + 元素2为头结点搜索树的数量 + 元素3为头结点搜索树的数量

    元素1为头结点搜索树的数量 = 右子树有2个元素的搜索树数量 * 左子树有0个元素的搜索树数量

    元素2为头结点搜索树的数量 = 右子树有1个元素的搜索树数量 * 左子树有1个元素的搜索树数量

    元素3为头结点搜索树的数量 = 右子树有0个元素的搜索树数量 * 左子树有2个元素的搜索树数量

    有2个元素的搜索树数量就是dp[2]。

    有1个元素的搜索树数量就是dp[1]。

    有0个元素的搜索树数量就是dp[0]。

    所以dp[3] = dp[2] * dp[0] + dp[1] * dp[1] + dp[0] * dp[2]

    1. 确定dp数组(dp table)以及下标的含义
      dp[i] : 1到i为节点组成的二叉搜索树的个数为dp[i]。
    2. 确定递推公式
      dp[i] += dp[j - 1] * dp[i - j]; ,j-1 为j为头结点左子树节点数量,i-j 为以j为头结点右子树节点数量
    3. dp数组如何初始化
      初始化,只需要初始化dp[0]就可以了,推导的基础,都是dp[0]。根据递推公式,dp[0] = 1.
    4. 确定遍历顺序
      首先一定是遍历节点数,从递归公式:dp[i] += dp[j - 1] * dp[i - j]可以看出,节点数为i的状态是依靠 i之前节点数的状态。那么遍历i里面每一个数作为头结点的状态,用j来遍历。
    5. 举例推导dp数组
      当 n = 5时,dp数组为[1,1,2,5,14,42]

    整体代码实现如下:

    class Solution {
    public:
        int numTrees(int n) {
            vector<int> dp(n + 1);
            dp[0] = 1;
            for (int i = 1; i <= n; i++) {
                for (int j = 1; j <= i; j++) {
                    dp[i] += dp[j - 1] * dp[i - j];
                }
            }
            return dp[n];
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  • 相关阅读:
    ssh连接远程服务器,并在终端安装anaconda
    Python爬虫入门:如何设置代理IP进行网络爬取
    crypto:丢失的MD5
    【案例教学】华为云API图像搜索ImageSearch的快捷性—AI帮助您快速归类图片
    数值类型表示二——定点和浮点格式
    Hadoop大数据初入门----haddop伪分布式安装
    Linux crontabs定时执行任务
    第十七章·命令模式
    爬虫基本原理介绍、实现以及问题解决
    垃圾回收 -标记清除算法
  • 原文地址:https://blog.csdn.net/qq_70244454/article/details/128182442