python算法与数据结构---动态规划

news2024/11/25 12:27:00

动态规划

记不住过去的人,注定要重蹈覆辙。

定义

对于一个模型为n的问题,将其分解为k个规模较小的子问题(阶段),按顺序求解子问题,前一子问题的解,为后一子问题提供有用的信息。在求解任一子问题时,通过决策求得局部最优解,依次解决各子问题。最后通过简单的判断,得到原问题的解。

经典案例—斐波那契数列

斐波那契数列又称黄金分割数列。因数学家莱昂纳多-斐波那契以兔子繁殖为例引入,故又称兔子数列。

1, 1, 2, 3, 5, 8, 13, 21...

在数学上满足递推的方法定义:

F(0) = 0
F(1) = 1
F(n) = F(n-1) + F(n-2)  (n>=2)
def fib(n):
	if n <= 0:
		return 0
	if n == 1:
		return 1
	return fib(n-1) + fib(n-2)

在这里插入图片描述
分析:
上图中的二叉树的每个子节点都需要执行一次,如果n= 6,则需要再向下延申,fib(2)就需要执行5次。每次调用时都需要保留上下文,在时间和空间上开销很大。那如果我们把每次计算的结果保存起来,下次用到的时候直接通过查表得方式调用,就可以节省大量得时间,这就是动态规划得基本思想。

动态规划解决

def fib_dp(n):
	#定义一个dp数组,记录每个n的值,这里n+1长度的便于写代码
	dp = [-1] * (n+1)
	#初始化
	dp[1] = dp[2] = 1
	for i in range(3, n+1):
		dp[i] = dp[i-1] + dp[i-2]
	return dp[n]

解题步骤

核心思想是递推,难点在于dp[i]状态代表什么,然后构造转移矩阵,利用初始条件递推出最终结果。
解题步骤:

  1. 划分阶段:按照问题的时间和空间特征,把若干问题分为若干个阶段。在划分阶段时,注意划分后的阶段一定要有序或者是可排序的,否则问题就无法求解。
  2. 确定状态和状态变量:将问题发展到各个阶段时所处于的各种客观情况用不同的状态表示出来。当然,状态的选择要满足无后效性。
  3. 确定决策并写出状态转移方程:因为决策和状态转移有着天然的联系,状态转移就根据上一阶段的状态和决策来导出本阶段的状态。所以确定了决策,状态转移方程也就可写出。但事实上常常是反过来的,根据相邻两个阶段的状态之间的关系来确定决策方法和状态转移方程。
  4. 寻找边界条件:给出的状态转移方程是一个递推式,需要一个递推的终止条件或边界条件。

动态规划算法的性质

动态规划的要素:问题的最优解由相关子问题的最优解组合而成,并且可以独立求解子问题(最优子结构)。

  • (1)最优化原理:如果问题的最优解包含的子问题也是最优的,就称该问题具有最优子结构,即满足最优化原理;
  • (2)无后效性:即某阶段状态(定义的新子问题)一旦确定,就不受这个状态以后决策的影响,也就是说,某状态以后的过程不会影响以前的状态,只与其以前的状态有关。

LeetCode例题

62不同路径

https://leetcode.cn/problems/unique-paths/description/
在这里插入图片描述
思路:
每一步只能从向下或向右移动一步,所以对于坐标(i,j)要么从(i-1,j)过来(向下走一步),要么从(i,j-1)过来(向右走一步)。

状态定义:
dp(i, j)表示从左上角走到(i,j)的路径数量

class Solution:
    def uniquePaths(self, m: int, n: int) -> int:
        #定义dp数组,用dp(i,j)表示从左上角走到(i,j)的路径数量dp(i,j)
        dp = [[0] * n for _ in range(m)]

        # 初始化dp数组,第一行和第一列、应该都是1,都只有一种情况,从左边或者上边过来
        dp[0][0] = 1
        for i in range(m):
            dp[i][0] = 1
        for j in range(n):
            dp[0][j] = 1
        
        #print(dp) # 可以看下dp  [[1, 1, 1, 1, 1, 1, 1], [1, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0]]
        #计算剩余位置,填充好dp数组
        for i in range(1, m):
            for j in range(1, n):
                dp[i][j] = dp[i-1][j] + dp[i][j-1]
        print(dp)  # [[1, 1, 1, 1, 1, 1, 1], [1, 2, 3, 4, 5, 6, 7], [1, 3, 6, 10, 15, 21, 28]]
        ## 通过查表的方式,返回最终结果
        return dp[m-1][n-1]

LCR 099. 最小路径和

https://leetcode.cn/problems/0i0mDW/description/
在这里插入图片描述
思路:
与上一题类似,对于坐标(i,j)要么从(i-1,j)过来(向下走一步),要么从(i,j-1)过来(向右走一步),但是加了条件,每个坐标上的值有了意义,需要进行累加处理。

状态:

设dp为大小m*n的矩阵,其中dp(i,j)的值代表直到走到(i,j)的最小路径和。

转移方程:

  1. 当可以从左边和上面过来,即左边和上边都不是矩阵边界时:
    dp(i, j) = grid(i, j) + min(dp(i-1, j), dp(i, j-1))
    
  2. 当只能从上边过来,即左边是矩阵边界时:
    dp(i, j) = grid(i, j ) + dp(i, j-1)
    
  3. 当只能从左边过来,即上边是矩阵边界时(i=0)
    dp(i, j) = grid(i, j) + dp(i, j-1)
    
  4. 在起点时(i=0, j=0)
    dp(i, j) = grid(i, j)
    
class Solution:
    def minPathSum(self, grid: List[List[int]]) -> int:
        rows = len(grid)
        cols = len(grid[0])

        #其中dp(i, j)的值代表直到走到(i,j)的最小路径和
        dp = [[0] * cols for _ in range(rows)]

        for i in range(rows):
            for j in range(cols):
                #起点
                if i == 0 and j == 0:
                    dp[i][j] = grid[i][j]
                # 中间的点,可以从左边和上边过来
                elif i != 0 and j != 0:
                    dp[i][j] = grid[i][j] + min(dp[i-1][j], dp[i][j-1])
                #只能从左边过来
                elif i == 0 and j != 0:
                    dp[i][j] = grid[i][j] + dp[i][j-1]
                #只能从上边过来
                elif i != 0 and j == 0:
                    dp[i][j] = grid[i][j] + dp[i-1][j]
        #print(dp) # grid =[[1,3,1],[1,5,1],[4,2,1]]
        return dp[rows-1][cols-1]

1884. 鸡蛋掉落-两枚鸡蛋

https://leetcode.cn/problems/egg-drop-with-2-eggs-and-n-floors/description/
在这里插入图片描述
思路:

开始有两枚鸡蛋,所以要分情况讨论,还剩两枚鸡蛋,和一枚鸡蛋;

  • 1、如果只有一枚鸡蛋:此时我们需要从1层逐层校验,才能获得确切的值,
  • 2、如果有两枚鸡蛋:第一次操作可以在任意一层,如果在k层丢下时碎了一个,那问题就转换成了第一点。

状态:

dp(i, j)表示有 i+1 鸡蛋时,验证 j 层楼需要的最少操作次数,我们可以分开分析 i = 0 和 i = 1的情况:

  • ·i = 0 时(只有一枚鸡蛋了):
    需要逐层检验,当在 j 层楼时,则dp(0, j) = j

  • i = 1时:

    • (1)假设当前在k层的时候第一枚鸡蛋碎了,那么问题就转换成了dp(0, k-1),总共的操作次数是,dp(0, k-1) + 1;

    • (2)如果当前在k层丢下鸡蛋,没有碎,此时可以证明在k层的时候鸡蛋不会碎,那么问题就转化成dp(1, j-k),总共的操作次数是dp(1, j-k) + 1

    • 基于(1)(2)取最坏情况:

      max(dp(0, k-1), dp(1, j-k) + 1)

    • 综上,

      dp(1, j) = min(dp(1, j), max(dp(0, k-1), dp(1, j-k) + 1))

转移方程:

dp(0, j) = j, i=0
dp(1, j) = min(dp(1, j), max(dp(1, j), max(dp(0, k-1), dp(1, j-k) + 1))), i=1

class Solution:
    def twoEggDrop(self, n: int) -> int:
        # dp(i, j)表示有i+1枚鸡蛋时,验证j层楼需要的最少操作次数
        dp = [[sys.maxsize] * (n + 1) for _ in range(2)]

        #初始化dp数组
        dp[0][0] = dp[1][0] = 0 
        
        #初始化,只有一枚鸡蛋的情况
        for j in range(n+1):
            dp[0][j] = j
        
        for j in range(n+1):
            #两枚鸡蛋时,在k层是否碎了,分情况讨论
             for k in range(j + 1):
                 dp[1][j] = min(dp[1][j], max(dp[0][k-1] + 1, dp[1][j-k] + 1))

        # 查表返回最终结果
        return dp[1][n]

附录基础

python数据结构与算法理论基础(专栏)

数据结构与算法(python)http://t.csdnimg.cn/Gb6MN

程序 = 数据结构 + 算法;而且在面试过程中这些是必考,必问的内容。内容大纲:基础数据结构(树、链表、栈、队列等)、常见算法(排序算法、递归算法等)。

专栏是基于python的基础知识,是很好的入门学习资料。帮助大家快速理解这些数据结构和常见算法的概念,同时结合力扣题目,也能更好的掌握这些知识,达到在面试中游刃有余的效果。

python基础语法

python基础精讲 http://t.csdnimg.cn/HdKdi

本专栏主要针对python基础语法,帮助学习者快速接触并掌握python大部分最重要的语法特征。
1、基本数据类型和变量
2、分支结构与循环结构
3、函数与异常处理
4、类与模块
5、文件读写
通过本专栏可以快速掌握python的基础语法。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Multisim14.0仿真(四十一)交通信号灯仿真设计

一、功能简介&#xff1a; 1&#xff09;、采用两片74LS192做减法计数器&#xff0c;实现倒计时功能。 2&#xff09;、采用DCD数码管显示时间。 3&#xff09;、采用4个TRAFFIC_LIGHT_SINGLE红绿灯 4&#xff09;、采用74LS160和74LS138实现对红绿灯的逻辑控制。 5&#xff09…

Python 潮流周刊#38:Django + Next.js 构建全栈项目

△△请给“Python猫”加星标 &#xff0c;以免错过文章推送 你好&#xff0c;我是猫哥。这里每周分享优质的 Python、AI 及通用技术内容&#xff0c;大部分为英文。本周刊开源&#xff0c;欢迎投稿[1]。另有电报频道[2]作为副刊&#xff0c;补充发布更加丰富的资讯&#xff0c;…

elementUI 表格中如何合并动态数据的单元格

elementUI 表格中如何合并动态数据的单元格 ui中提供的案例是固定写法无法满足 实际开发需求 下面进行改造如下 准备数据如下 //在表格中 设置单元格的方法 :span-method"spanMethodFun" <el-table :data"tableData" border :span-method"spa…

私有化部署一个吃豆人小游戏

目录 效果 安装步骤 1.安装并启动httpd 2.下载代码 3.启动httpd 使用 效果 安装步骤 1.安装并启动httpd yum -y install httpd 2.下载代码 进入目录 cd /var/www/html/ 下载 git clone https://gitee.com/WangZhe168_admin/pacman-canvas.git 3.启动httpd syste…

docker更换镜像源

添加的镜像源 {"registry-mirrors": ["https://registry.cn-hangzhou.aliyuncs.com", "https://reg-mirror.qiniu.com/", "https://docker.mirrors.ustc.edu.cn"] }docker更换镜像源之后一定要重启守卫 systemctl daemon-reloaddock…

网络原理TCP/IP(5)

文章目录 IP协议IP协议报头地址管理网段划分特殊的IP地址路由选择以太网认识MAC地址对比理解MAC地址和IP地址DNS&#xff08;域名服务器&#xff09; IP协议 IP协议主要完成的工作是两方面&#xff1a; 地址管理&#xff0c;使用一套地址体系&#xff0c;来描述互联网上每个设…

响应式开发如何设置断点,小屏幕界面该如何显示(有动图)

Hi&#xff0c;我是贝格前端工场&#xff0c;本期分享响应式开发&#xff0c;如何设置屏幕断点&#xff0c;pc页面布局到了移动端之后该如何布局的问题&#xff0c;微软也提供了设置屏幕断点的动图演示&#xff0c;非常直观。 一、什么是响应式开发&#xff0c;为何要设置屏幕断…

问题:0xc8前面加(byte) #人工智能#学习方法的原因是因为0xc8大于??????????? 。 #微信#其他#微信

问题&#xff1a;0xc8前面加&#xff08;byte&#xff09;的原因是因为0xc8大于??????????? 。 参考答案如图所示

【Linux】信号-下

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;折纸花满衣 &#x1f3e0;个人专栏&#xff1a;题目解析 &#x1f30e;推荐文章&#xff1a;【LeetCode】winter vacation training 目录 &#x1f449;&#x1f3fb;信号递达&#xff0c;信号未决&#x…

【MySQL】DQL的总结和案例学习

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-VWRkWqFrRMi4uLRa {font-family:"trebuchet ms",verdana,arial,sans-serif;font-siz…

华为自动驾驶干不过特斯拉?

文 | AUTO芯球 作者 | 李诞 什么&#xff1f; 华为的智能驾驶方案干不过蔚小理&#xff1f; 特斯拉的智能驾驶[FSD]要甩中国车企几条街&#xff1f; 这华为问界阿维塔刚刚推送“全国都能开”的城区“无图 NCA” 就有黑子来喷了 这是跪久了站不起来了吧 作为玩车14年&…

知识图谱概论

知识图谱 1 学习目标2 知识图谱概念2.1 什么是知识图谱2.2 语义网络2.3 知识图谱的定义 3 知识图谱的架构3.1 知识图谱的逻辑结构3.2 知识图谱的体系架构 4 知识图谱的关键技术4.1 信息抽取4.2 知识融合4.3 知识加工4.4 知识图谱存储4.5 知识更新 5 知识图谱的典型应用5.1 智能…

基于Bazel实现C++/Python编译

最近在学Baidu Apollo需要用到Bazel进行编译&#xff0c;在此记录下Bazel的学过程&#xff0c;以及遇到的一些问题和心得。另外强烈推荐B站赵虚左老师的Cyber RT课程&#xff0c;里面对Bazel的使用有详细的教学。 下面的使用过程都是在Ubuntu 22.04上进行的&#xff0c;首先需要…

Cassandra 命令大全

文章目录 1. 连接与基本操作2. 数据库管理3. 表&#xff08;Column Family&#xff09;操作4. 集群管理5. 权限管理6. 其他高级功能7. 条件查询与聚合操作8. 索引管理9. 用户权限和角色管理10. 安全性相关设置11. 一致性级别控制12. 用户定义类型 (UDTs)13. 用户定义函数 (UDFs…

2024年【天津市安全员C证】考试报名及天津市安全员C证免费试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年天津市安全员C证考试报名为正在备考天津市安全员C证操作证的学员准备的理论考试专题&#xff0c;每个月更新的天津市安全员C证免费试题祝您顺利通过天津市安全员C证考试。 1、【多选题】下列说法正确的是&#…

ChatGPT生产力|chat gpt实战介绍

标注说| ⭐ : 使用稳定&#xff0c;推荐 | &#x1f604; : 免费使用 | &#x1f511; : 需要登陆或密码 | ✈️ : 需waiwang进行访问 | ChatGPT 1PoePoe - Fast, Helpful ...&#x1f511;&#x1f604;&#x1f517;2 AItianhuGPT4&#x1f604;⭐&#x1f517;3 PhantoNa…

Vue ElementUI中el-table表格嵌套样式问题

一、表格嵌套要求&#xff1a; 两个表格嵌套&#xff0c;当父表格有children数组时子表格才展示&#xff1b;子表格数据少于父表格展示字段&#xff0c;且对应固定操作列不同&#xff1b; 二、嵌套问题&#xff1a; 当使用el-table的typeexpand实现表格嵌套时&#xff0c;样…

ChatGPT Plus如何升级?信用卡付款失败怎么办?如何使用信用卡升级 ChatGPT Plus?

ChatGPT Plus是OpenAI提供的一种高级服务&#xff0c;它相较于标准版本&#xff0c;提供了更快的响应速度、更强大的功能&#xff0c;并且用户可以优先体验到新推出的功能。 尽管许多用户愿意支付 20 美元的月费来订阅 GPT-4&#xff0c;但在实际支付过程中&#xff0c;特别是…

(2)(2.13) Rockblock Satellite Modem

文章目录 前言 1 支持的MAVLink命令信息 2 设置 3 使用方法 4 数据成本 5 参数 前言 &#xff01;Note 该功能仅适用于 ArduPilot 4.4 或更高版本&#xff0c;并且要求飞行控制器支持 LUA 脚本(LUA Scripts)。 RockBLOCK 卫星调制解调器可实现与 ArduPilot 飞行器的全球…

【MySQL】- 09 Select Count

【MySQL】- 09 Select Count 1认识COUNT2 COUNT(列名)、COUNT(常量)和COUNT(*)之间的区别3 COUNT(*)的优化 4 COUNT(*)和COUNT(1)5 COUNT(字段)总结 数据库查询相信很多人都不陌生&#xff0c;所有经常有人调侃程序员就是CRUD专员&#xff0c;这所谓的CRUD指的就是数据库的增删…