当前位置: 首页 > news >正文

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

343. 整数拆分

题目链接:link
文章讲解:link
视频讲解:link

一、做题感受&第一想法

其实第一反应是回溯……但感觉每层的集合都会很繁琐

二、学习文章后收获

1.动态规划思路

  • 动规五要素分析

    • dp和i的定义:dp[i]指把i拆分后最大乘积(所以dp[1]、dp[0]都没有太大意义,因为0和1拆了乘积也是0)
    • 递归公式:dp[i] = max(j * (i - j) , j * dp[i - j]), 1 <= j < i - 1(j<i-1是为什么?因为j = i-1时,dp[j-i]也就是dp[1]为0,没有意义;而 j*(i-j)也就是(i-1)*1,这和 j=1重复了,所以可以省去j = i-1的讨论!)
    • 初始化:dp[0] = 0,dp[1] = 0,dp[2] = 1
    • 遍历顺序:从前往后
    • 手算序列(略)
  • 递归公式的说明:求dp[i]可分成两种情况

    • 把 i 拆成 j 和 i - j 两个数,总共两个数。
    • 把 i 拆成 j 和"和为 i - j 的若干个数",总共大于等于三个数。
class Solution {
public:int integerBreak(int n) {vector<int> dp(n+1,0); //dp[i]:拆分i得到的最大乘积dp[0] = 0;dp[1] = 0; //其实这俩初始化无所谓,因为没有意义dp[2] = 1; // 1*1for(int i = 3;i <= n;i++){for(int j = 1;j < i - 1;j++){dp[i] = max(dp[i],max(j*(i-j),j*dp[i-j]));}}return dp[n];}
};

2.动态规划优化

思路:for循环上的剪枝,剪枝依据是,要想找到乘积最大的拆分方式,需要让拆出来的所有数字尽可能大小相似。所以,对于太大的 j ,可以直接跳过。
故内层for的条件改为 j <= i/2:for (int j = 1; j <= i / 2; j++)

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++) { //here!dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j));}}return dp[n];}
};

2.贪心思路

思路:本题也可以用贪心,每次拆成n个3,如果剩下是4,则保留4,然后相乘,但是这个结论需要数学证明其合理性!

此处没有证明,而是直接用了结论。

说明:
if(n == 2) return 1;
if(n == 3) return 2;
if(n == 4) return 4;
剩下的,拆成3的和,直到剩下4或者不足3(也就是前面是一堆3,最后剩下的值<=4即停止,作为最后一个数字)。

class Solution {
public:int integerBreak(int n) {if(n == 1 || n == 0) return 0;if(n == 2) return 1;if(n == 3) return 2;if(n == 4) return 4;int remains = n - 3,result = 3;while(remains > 4){result *= 3;remains -= 3;}result *= remains;return result;}
};

三、过程中遇到的问题

1.多个数取最大

max(a,max(b,c))


96.不同的二叉搜索树

题目链接:link
文章讲解:link
视频讲解:link

一、做题感受&第一想法

  • 动规五要素分析
    • dp和i的定义:dp[i]指 i 个节点的二叉搜索树共有多少种树型
    • 递归公式:dp[i] += dp[j] * dp[i-j-1], 0 <= j <= i - 1(左子树 j 个节点,右子树 i - j - 1个节点。总树型为 左子树的树型数 乘以 右子树的树型数)
    • 初始化:dp[0] = 1,dp[1] = 1
    • 遍历顺序:从前往后
    • 手算序列(略)
class Solution {
public:int numTrees(int n) {vector<int> dp(n+1,0);dp[0] = 1;dp[1] = 1;for(int i = 2;i <= n;i++){ //dp[i]for(int j = 0;j <= i - 1;j++){ //左子树:j,右子树:i-j-1dp[i] += dp[j] * dp[i-j-1]; //递推公式}}return dp[n];}
};

http://www.lryc.cn/news/317460.html

相关文章:

  • 二叉树算法
  • 【2024年5月备考新增】《软考真题分章练习(答案解析) - 4 项目范围管理(高项)》
  • Docker拉取镜像存储不足
  • JUNIT5+Mockito单元测试
  • 【C#】【SAP2000】读取SAP2000中所有Frame对象的应力比到Grasshopper中
  • 一台服务器部署两个独立的mysql实例
  • SpringBoot(Lombok + Spring Initailizr + yaml)
  • 数据库基础知识超详细解析~‍(进阶/复习版)
  • 创建对象的方法有哪些
  • Oracle 10g字符编码
  • 掌握抽象基础之20个必备原则,看完你还不会,你打我
  • 设计模式 -- 2:策略模式
  • 【快速上手ProtoBuf】proto 3 语法详解
  • 人工智能的幽默“失误”
  • js的异步请求?
  • 华润对象存储(OBS)工具类
  • 强缓存和协商缓存的区别?
  • ChatGPT提问技巧——对抗性提示
  • openGauss使用BenchmarkSQL进行性能测试(上)
  • Java的线程池机制
  • EasyCode 插件的具体使用
  • Ypay源支付6.9无授权聚合免签系统可运营源码
  • SpringBoot+Vue项目报错(问题已解决)
  • DEAP 自定义交叉操作
  • ByText
  • Vcenter esxi web界面访问提示权限被拒绝
  • 掌握FilterOutputStream类!
  • YOLOv8改进 | 图像去雾 | 特征融合注意网络FFA-Net增强YOLOv8对于模糊图片检测能力(北大和北航联合提出)
  • Python (用户登录、身份归属地查询添加异常处理、绘制多角星、电影信息提取)
  • Set cancelled by MemoryScratchSinkOperator