代码随想录Day41:动态规划Part3

Leetcode 343. 整数拆分

讲解前:

毫无头绪

讲解后:

这道题的动态思路一开始很不容易想出来,虽然dp数组的定义如果知道是动态规划的话估摸着可以想出来那就是很straight forward

dp定义:一维数组dp[i], i 代表整数的值,dp[i] 代表将整数 i 拆分的话可以获得的最大乘积

然后呢就是定义递归推导式了,我们可以这样去想这道题,既然题目要求我们拆分的话必须要最少有两个数,那么其实可以把获得最大乘积的可能分为两种情况,对于每一个整数 i,我们进行一个遍历,让 j 从 1 遍历到 i - 1,也就是当 i = 5的时候,j遍历1,2,3,4 这样的话相当于我们可以找到拆分成两个数的所有可能,那么第一种情况就是: 最大的乘积是从 j * (i - j) 中获取的,也就是1*4, 2*3, 3* 2, 4*1, 第二种情况就会变成:最大乘积是从3个以上的数字中获得的,意味着我们会对 i - j 遍历到的数字进行拆分,那么如果我们刚好能得到 拆分 j - i 的乘积最大值,那么再和 j 相乘,一定就也是当我们用三个以上数字的最大乘积,那拆分 j 的乘积最大值是多少呢?不就刚好是 dp[i - j] 吗,下面我画了当 i 是3,4,5 的时候我们会计算的所有值

 

你会发现这样的话,对于三个数以上的可能,我们也完全不用担心会错过一些组合,由于动态递归的帮助,我们在计算出一个dp[i] 的值之前,就已经考虑过了所有的可能

这里还要注意一点, 以上的计算,只是在当整数是 i 的时候,我们在比较到底是当我们之后 j * (i - j)两个数相乘的时候有更大乘积,还是当我们有 j * 拆分(j - i) 一共三个数以上的时候有更大的乘积,但是我们并不知道当 j 遍历到哪的时候会得到所有可能中最大的乘积,所以在推导式中还要再加入一个比较就是一直更新保持dp[i] 储存遍历过程中最大的值

那么我们就可以总结出来递归推导公式

dp[i] = max(dp[i], max(j * (i - j), j * dp[i - j]))

class Solution:
    def integerBreak(self, n: int) -> int:
        dp = [0] * (n + 1)
        dp[2] = 1

        for i in range(3, n + 1):
            for j in range(1, i):
                dp[i] = max(dp[i], max(j * (i - j), j * dp[i - j]))
                print(dp)
        
        return dp[n]

Leetcode 96. 不同的二叉搜索树

讲解前:

太难了

讲解后:

这道题首先我们可以把从n=1到n=3的所有可能画出来

观察上面的图,仔细去看其中的规律,我们其实可以总结出来两个非常重要的点来帮助我们推导我们的dp推导公式

1. 对于任何n个节点从1到n不相同的平衡二叉树,其实所有的组合是首先我们把1作为root节点,找到有多少种组合,然后再把2作为头节点,然后去找有多少组合,再把3作为头节点,去找有多少种组合.......直到把n作为头节点,看有多少组合,然后全部加起来,就如上图的n=3,答案5=2(1 as root) + 1(2 as root) + 2(3 as root) 个组合 

2. 对于二叉树来说,如果我们能够知道左子树一共有多少种组合,并且直到右子树一共有多少种组合,那么其实这个二叉树一共就有左子树组合数 * 右子树组合数 数量的组合,因为每一个特别的左子树都可以和每一个特别的右子树结合来构造一个新的树,举个例子的话就是上图中的在n=3并且我们的root是1的时候,我们有两种组合,其实这两种组合是这样得来的,我们知道root=1的时候,左子树没有节点的时候有一个可能,就是空,也就是左子树的组合数为1,然后呢右子树的话,由2和3两个节点组成,他们有两种可能,分别是让3在2的右节点,或者2在3的左节点,这样以来我们就知道对于root=1的时候,我们一共有1*2=2种组合

有了上面两个概念,首先我们可以把动态规划数组的含义想出来,还是很简单,直接按照题意来写

dp[i], i是n,也就是当我们的二叉平衡树是由1-n节点组成的,dp[i] 储存的值就是有多少种不同的可能来构建这个二叉平衡树

接下来我们可以去想,那既然我们知道了上面的概念,那么我们首先可以确定,在每一个dp[i] 求值的过程中,我们需要进行一个叠加,这个叠加就是概念1,就是用 j 来从1-n遍历,找到当 j 为root的时候,每个二叉树分别有多少种构造方法,那这个该怎么找呢?我们发现,当我们知道root=j 的时候,其实左右两个节点分别含有多少节点我们是知道的,因为我们知道一共有1-n个节点并且没有重复,那假设我们有1-10个节点,如果root取7,我们就知道那左子树一定有6个节点分别是1-6,然后右子树有3个节点是8,9,10,这是用 j - 1和,i - j 得来的,那这不就方便了吗,通过概念2我们知道,不同二叉树的数量就等于左子树的变化数量 * 右子树的变化数量,我们还知道左子树的节点数量和右子树的节点数量,知道了节点数量,找变化数量,不就是我们dp数组的含义吗,所以这个时候我们就可以先按照上图中的n=3的情况,写一下这个答案5是怎么得来的

dp[3] = dp[0] * dp[2] (root=1) + dp[1] * dp[1] (root=2) + dp[2] * dp[0] (root=3),这样以来我们就可以推导出公式了

j 为root的元素然后从 1 遍历到 i, 然后dp[i] 的值做一个叠加,分别是j不同值的答案总和

dp[i] = dp[i] + dp[j - 1] * dp[i - j]

 dp推导公式搞明白之后代码就不难了,遍历顺序就是正常的从左到右,我们要先知道小的n才能推理出后面的n,然后呢初始化就是没有节点和就一个节点的组合数量都是1, dp[0] = 1, dp[1] = 1

class Solution:
    def numTrees(self, n: int) -> int:
        # initialize the dp array 
        # have it set to length of n + 1 cuz the answer is dp[n]
        dp = [0] * (n + 1)
        # we know only 1 possibility for n = 0 and 1
        dp[0], dp[1] = 1, 1

        # start iteration from when we have 2 nodes
        for i in range(2, n + 1):
            for j in range(1, i + 1):
                dp[i] = dp[i] + dp[j - 1] * dp[i - j]
        
        return dp[n]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/547685.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

5.paramiko模块使用

目录 概述实践安装paramikoparamiko包括两个核心的组件paramiko有几个基础的名词 SSHClient使用常用方法例子例子2 SFTPClient类案例 结束 概述 paramiko是实现远程控制 实践 安装 pip install paramiko paramiko SSH是一个协议,paramiko是使用SSHv2协议(底层使…

OpenCV基本图像处理操作(一)——图像基本操作与形态学操作

环境配置地址 图像显示 import cv2 #opencv读取的格式是BGR import numpy as np import matplotlib.pyplot as plt#Matplotlib是RGB imgcv2.imread(cat.jpg) img_gray cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) img_gray.shape cv2.imshow("img_gray", img_gray) cv2…

Deep Learning for Single Image Super-Resolution: A Brief Review

TMM 2019 用深度学习来解决SISR问题(single image super resolution)的问题,从两个方面 高效的网络结构,efficient architectures;有效的优化目标,OPTIMIZATION OBJECTIVES; 问题的定义 由LR y y y恢复HR x x x&a…

c++总结笔记(一)

计算机可以将程序转化为二进制指令(即机器码),并由CPU执行,CPU会按照指令的顺序依次执行每个指令。 C语言特点: 简洁高效可移植模块化标准化 C语言的标准 C89(C90)标准C99标准C11标准 导入 使用include导入包含…

阿里云Centos7下编译glibc

编译glibc 原来glibc版本 编译前需要的环境: CentOS7 gcc 8.3.0 gdb 8.3.0 make 4.0 binutils 2.39 (ld -v) python 3.6.8 其他看INSTALL, 但有些版本也不易太高 wget https://mirrors.aliyun.com/gnu/glibc/glibc-2.37.tar.gz tar -zxf glibc-2.37.tar.gz cd glibc-2.37/ …

Linux中断——嵌入式Linux驱动开发

参考正点原子I.MX6U嵌入式Linux驱动开发指南 一、简介 先来简单了解一般中断的处理方法: ①、使能中断,初始化相应的寄存器。 ②、注册中断服务函数,也就是向 irqTable 数组的指定标号处写入中断服务函数 ③、中断发生以后进入 IRQ 中…

YOLOv8改进 添加大核卷积序列注意力机制LSK

一、Large Separable Kernel Attention论文 论文地址:2309.01439.pdf (arxiv.org) 二、Large Separable Kernel Attention注意力结构 LSK通过使用大型可分离卷积核来提升注意力机制的效果。在传统的注意力机制中,常用的是小型卷积核,如1x1卷积,来计算注意力权重和特征表示…

坦桑尼亚公司注册

哈喽大家好我是小鱼~ 很多朋友想了解坦桑尼亚公司的注册信息,今天来给大家分享: 坦桑尼亚随着投资环境的不断改善,成为非洲区域贸易集团成员,更好的为公司提供了广阔的非洲市场基础和劳动力优势,与20多个国家签订了避…

海外云手机怎么解决tiktok运营难题?

最近打算做TikTok的商家越来越多了,而做TikTok的第一步就面临如何养号、涨粉的困境,本文将介绍如何通过海外云手机轻松解决这些问题。 早期大家用的比较多的,是真机科学上网的方法。但是这种方法,需要自己搭建海外环境&#xff0c…

【小程序】生成短信中可点击的链接

文章目录 前言一、如何生成链接二、仔细拜读小程序开发文档文档说明1文档说明2 总结 前言 由于线上运营需求,需要给用户发送炮轰短信,用户通过短信点击链接直接跳转进入小程序 一、如何生成链接 先是找了一些三方的,生成的倒是快速&#xf…

BCLinux8U6系统部署oceanbase分布式数据库社区版之二、数据库服务器准备

本文是在完成步骤一、准备 OBD 中控机后的第二步,准备3台oceanbase分布式数据库服务器。 前序步骤:BCLinux8U6系统部署oceanbase分布式数据库社区版之一、准备 OBD 中控机 一、服务器配置 1、服务器硬件配置 本例采用vmware虚拟机来构建测试平台&…

c++ 多文件编程

1.结构目录 声明类:用于声明方法,方便方法管理和调用; 实现类:用于实现声明的方法; 应用层:调用方法使用 写过java代码的兄弟们可以这么理解: 声明类 为service层 实现类 为serviceimpl层 应用层 为conlloter层 2.Dome 把函数声明放在头文件xxx.h中&…

端口映射软件可以做什么? 快解析如何设置端口映射?

说到端口映射,首先说说nat。简单地说,nat就是在局域网内部网络中使用内部地址,而当内部节点要与外部网络进行通讯时,就在网关处,将内部地址替换成公用地址,从而在外部公网(internet)…

自定义类似微信效果Preference

1. 为自定义Preference 添加背景&#xff1a;custom_preference_background.xml <?xml version"1.0" encoding"utf-8"?> <selector xmlns:android"http://schemas.android.com/apk/res/android"><item><shape android:s…

nginx的启动,systemd管理

service unit file文件通常由三部分组成&#xff1a; [Unit]&#xff1a;定义与Unit类型无关的通用选项&#xff1b;用于提供unit的描述信息、unit行为及依赖关系等 [Service]&#xff1a;与特定类型相关的专用选项&#xff1b;此处为Service类型 [Install]&#xff1a;定义…

AI人工智能学习指南:入门必备的五大步骤

人工智能的发展正以前所未有的速度推动着技术、商业和社会的变革。在这个迅速发展的领域中&#xff0c;个人掌握新技能和知识至关重要。在这篇文章中&#xff0c;我将为您提供一份人工智能学习指南&#xff0c;帮助您打开人工智能的大门。 1.了解人工智能的基本概念和应用 人工…

表单自定义系统源码:自主创建表单 带完整的安装代码包以及搭建教程

在当今信息化社会&#xff0c;表单作为一种常见的数据收集工具&#xff0c;广泛应用于各类网站和系统中。然而&#xff0c;传统的表单系统往往功能单一&#xff0c;缺乏灵活性&#xff0c;难以满足用户多样化的需求。下面&#xff0c;小编给大家分享一款表单自定义系统源码&…

OpenAI官宣位于东京的首个亚洲办公室,并将发布专为日语优化的GPT-4定制模型!

大家好&#xff0c;我是木易&#xff0c;一个持续关注AI领域的互联网技术产品经理&#xff0c;国内Top2本科&#xff0c;美国Top10 CS研究生&#xff0c;MBA。我坚信AI是普通人变强的“外挂”&#xff0c;所以创建了“AI信息Gap”这个公众号&#xff0c;专注于分享AI全维度知识…

vscode和pycharm等idea编写protobuf文件格式化

想在pycharm或者goland等idea中开发protobuf文件的话&#xff0c;可以安装一个插件&#xff1a;protocol-buffers 安装之后&#xff0c;proto文件就会支持高亮和格式化了。 如果是vscode想要编写proto文件&#xff0c;可以安装另外一个插件&#xff1a;vscode-proto3 安装后&a…

202303青少年软件编程(scratch图形化)等级考试试卷(四级)

第1题&#xff1a;【 单选题】 编写一段程序&#xff0c;从26个英文字母中&#xff0c;随机选出10个加入列表a。空白处应填入的代码是&#xff1f;&#xff08;&#xff09; A: B: C: D: 【正确答案】: C 【试题解析】 : 第2题&#xff1a;【 单选题】 运行以下代码&…