代码随想录算法训练营第四十一天|343. 整数拆分、96.不同的二叉搜索树

代码随想录算法训练营第四十一天|343. 整数拆分、96.不同的二叉搜索树

整数拆分

343. 整数拆分
文章讲解:https://programmercarl.com/0343.%E6%95%B4%E6%95%B0%E6%8B%86%E5%88%86.html
题目链接:https://leetcode.cn/problems/integer-break/
视频讲解:https://www.bilibili.com/video/BV1Mg411q7YJ/

自己看到题目的第一想法

看完代码随想录之后的想法

解题思路:尽量把数字拆成相同的数。
整体还是走动态规划五步骤:

  • 确定dp数组以及下标的含义
    • dp[i]:分拆数字i,可以得到的最大乘积为dp[i]
  • 确定递推公式
    • 如果是求最大积的话从1遍历j,有两种渠道得到dp[i]。一个是j*(i - j)直接相乘;一个是jdp[i - j],相当于拆分(i - j)。可以这么理解,j(i - j) 是单纯的把整数拆分为两个数相乘,而j * dp[i - j]是拆分成两个以及两个以上的个数相乘。所以递推公式:dp[i] = max({dp[i], max((i - j)*j, dp[i - j]*j}));
    • dp[i]中取最大值

自己实现过程中遇到哪些困难

整数拆分的递推公式有点没理解,如何处理遍历顺序,i=3,那j从什么位置开始。i=3的话,表示要分拆3,因此可以用j(i-j)以及j*dp[i-j]得到最大值。*

不同的二叉搜索树

96.不同的二叉搜索树
文章讲解:https://programmercarl.com/0096.%E4%B8%8D%E5%90%8C%E7%9A%84%E4%BA%8C%E5%8F%89%E6%90%9C%E7%B4%A2%E6%A0%91.html
题目链接:https://leetcode.cn/problems/unique-binary-search-trees/
视频讲解:https://www.bilibili.com/video/BV1eK411o7QA/

自己看到题目的第一想法

看完代码随想录之后的想法

n=3时
画出n=3的所有情况,再单独画出n=0时,n=1时,n=2的的情况
将整体分为头节点为1时、头节点为2时、头节点为3时的所有情况
头节点是1时=左子树0节点情况 * 右子树2节点数量情况
头节点是2时=左子树1节点情况 * 右子树1节点数量情况
头节点是3时=左子树2节点情况 * 右子树0节点情况
dp[3] = dp[0] * dp[2] + dp[1] * dp[1] + dp[2] * dp[0]

// 1. dp[i]的概念就是 n为i的情况下,组成所有二叉搜索树的情况
// 2. 递推公式
// 当以j为头节点时,左节点为j-1个,右节点为i-j个,因为dp[i]是组成所有二叉树的情况,因此dp[i] += dp[j-1]*dp[i-j]。是累加的情况就是j=1,j=2,j=3…求得的值。
// 3. 初始化值
// 4. 递推公式 从小到大

自己实现过程中遇到哪些困难

遇到题目时,先画图,然后再展开找规律会更好一些。

public int numTrees(int n) {
    // dp[i]的含义,为i个节点时的二叉搜索树种数
    // 递推公式:
    // n=3时
    // 当以1为根节点时,有2种组合,组合即位左边0的组合数*右边节点为2个节点时的组合数量。
    // 当以2为根节点时,有1种组合,左边1个*右边1个。
    // 当以3为根节点时,有2种组合,左边2个节点的组合钟数*右边0个组合种数
    // 当根节点为j时,左边有j-1个,右边有i-j个,dp[j-1]*dp[i-j]
    // 当给一个整数i时,dp[i] += dp[j-1]*dp[i-j];
    int[] dp = new int[n + 1];
    dp[0] = 1;
    dp[1] = 1;
    for(int i = 2; i <= n; i++){
        for(int j = 1;j <= i; j++){
            dp[i] += dp[j-1]*dp[i-j];
        }
    }
    return dp[n];

}

今日收获&学习时长

今天的2道题都是直接看视频,然后看答案的,看完答案然后自己手写一遍。还需要多重复刷几次。
学习时长:2小时

你可能感兴趣的:(算法)