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

动态规划

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

定义

对于一个模型为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 0if n == 1:return 1return 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] = 1for 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] = 1for i in range(m):dp[i][0] = 1for 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] = jfor 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.mzph.cn/news/668550.shtml

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

相关文章

全网第一篇把Nacos配置中心客户端讲明白的

入口 我们依旧拿ConfigExample作为入口 public class ConfigExample {public static void main(String[] args) throws NacosException, InterruptedException {String serverAddr "localhost";String dataId "test";String group "DEFAULT_GROU…

拍摄的视频怎么做二维码?视频在线转二维码的技巧

现在学校经常会将学生日常的拍摄的短片做成二维码之后展示给其他人&#xff0c;其他人可以通过扫描二维码来查看个人表现的视频&#xff0c;有些活动视频也会用视频二维码的方式来传播。那么视频二维码制作的方法及步骤是什么样的呢&#xff1f;下面就让小编通过本文来给大家介…

Eclipse 安装使用ABAPGit

Eclipse->Help->Install New software 添加地址 https://eclipse.abapgit.org/updatesite/ 安装完成打开 选择abapGit repositories,先添加仓库 点下图添加自己仓库 如图添加仓库地址 添加完仓库后&#xff0c;点击我的仓库 右键选中行&#xff0c;可以进行push和pu…

自动驾驶IPO第一股及商业化行业标杆 Mobileye

一、Mobileye 简介 Mobileye 是全球领先的自动驾驶技术公司&#xff0c;成立于 1999 年&#xff0c;总部位于以色列耶路撒冷。公司专注于开发视觉感知技术和辅助驾驶系统 (ADAS)&#xff0c;并在自动驾驶领域处于领先地位。Mobileye 是高级驾驶辅助系统&#xff08;ADAS&#…

Vscode编译运行多个C++文件

1.摘要 在使用Vscode编译单个文件网上很多教程&#xff0c;但是对多个文件编译会发现经常出问题&#xff0c;通过不断的借阅网友的教程改进终于完成C运行多个文件教程如下&#xff1a; 2.编译运行过程 2.1 初始配置过程 &#xff08;1&#xff09;Vscode以及MinGW配置教程很…

管理类联考-复试-全流程演练-导航页

文章目录 整体第一步&#xff1a;学校导师两手抓——知己知彼是关键学校校训历史 导师你对导师的研究方向有什么认知。 第二步&#xff1a;面试问题提前背——押题助沟通自我介绍——出现概率&#xff1a;100%为什么选择这个专业&#xff1f;今后如何打算&#xff1f;你认为自己…

高并发内存池项目

目录 项目简介什么是内存池池化技术内存池 内存池主要解决的问题定长内存池的设计高并发内存池的整体框架设计thread cachethread cache的整体设计thread cache哈希桶的对齐规则threadcacheTLS无锁访问 central cachecentralcache整体设计central cache 结构设计central cache核…

Redis——高级主题

介绍Redis的高级主题&#xff0c;包括服务器配置、Redis事务、Redis发布和订阅、Pipeline批量发送请求、数据备份与恢复等。 1、服务器配置 在Windows和Linux的Redis服务器里面&#xff0c;都有一个配置文件。Redis配置文件位于Redis安装目录下&#xff0c;在不同操作系统下&…

Redis核心技术与实战【学习笔记】 - 21.Redis实现分布式锁

概述 在《20.Redis原子操作》我们提到了应对并发问题时&#xff0c;除了原子操作&#xff0c;还可以通过加锁的方式&#xff0c;来控制并发写操作对共享数据的修改&#xff0c;从而保证数据的正确性。 但是&#xff0c;Redis 属于分布式系统&#xff0c;当有多个客户端需要争…

【Java知识手册】一.Java开发工具和前言

文章目录 1 Java前言1.1 简介1.2 Java环境搭建1.3 程序的开发步骤1.4 idea开发工具1.5用idea开发一个helloworld 前言&#xff1a;以初学着的身份&#xff0c;准备在该平台整理点最近学习的知识&#xff0c;方便后续查看相关的技术点&#xff0c;有兴趣的可以一块交流学习。目标…

机器学习本科课程 大作业 多元时间序列预测

1. 问题描述 1.1 阐述问题 对某电力部门的二氧化碳排放量进行回归预测&#xff0c;有如下要求 数据时间跨度从1973年1月到2021年12月&#xff0c;按月份记录。数据集包括“煤电”&#xff0c;“天然气”&#xff0c;“馏分燃料”等共9个指标的数据&#xff08;其中早期的部分…

接口测试要测试什么?

一. 什么是接口测试&#xff1f;为什么要做接口测试&#xff1f; 接口测试是测试系统组件间接口的一种测试。接口测试主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点。测试的重点是要检查数据的交换&#xff0c;传递和控制管理过程&#xff0c;以及系统间的相互…

Maven 安装教程

一、安装地址 1.官网安装最新版本 2.其他版本&#xff0c;我这里是maven-3/3.6.2 二、配置环境 1. 点击此电脑鼠标右击->属性->高级系统设置->环境变量 &#xff0c;配置系统变量->新建&#xff1a;MAVEN_HOME 2.配置path 路径 &#xff1a;%MAVEN_HOME%\bin 三、安…

ChatGPT之制作短视频

引言 今天带来了如何使用 ChatGPT和剪映来制作简单的短视频教程&#xff0c;在这其中 ChatGPT的作用主要是帮我们生成文案&#xff0c;剪映的功能就是根据文案自动生成视频&#xff0c;并配上一些图片、动画、字幕和解说。 ChatGPT生成文案 首先&#xff0c;我们需要使用提示…

Anaconda的安装及其配置

一、简介 Anaconda是一个开源的包、环境管理器&#xff0c;主要具有以下功能和特点&#xff1a; 提供conda包管理工具&#xff1a;可以方便地创建、管理和分享Python环境&#xff0c;用户可以根据自己的需要创建不同的环境&#xff0c;每个环境都可以拥有自己的Python版本、库…

常用排序算法(Java版本)

1 引言 常见的排序算法有八种&#xff1a;交换排序【冒泡排序、快速排序】、插入排序【直接插入排序、希尔排序】、选择排序【简单选择排序、堆排序】、归并排序、基数排序。 2 交换排序 所谓交换&#xff0c;就是序列中任意两个元素进行比较&#xff0c;根据比较结果来交换…

nginx slice模块的使用和源码分析

文章目录 1. 为什么需要ngx_http_slice_module2. 配置指令3. 加载模块4. 源码分析4.1 指令分析4.2 模块初始化4.3 slice模块的上下文4.2 $slice_range字段值获取4.3 http header过滤处理4.4 http body过滤处理5 测试和验证 1. 为什么需要ngx_http_slice_module 顾名思义&#…

程序员为什么不喜欢关电脑,这回答很霸道!

在大家的生活中&#xff0c;经常会发现这样一个现象&#xff1a;程序员经常不关电脑。 至于程序员不关电脑的原因&#xff0c;众说纷纭。 其中这样的一个程序员&#xff0c;他的回答很霸道&#xff1a; “因为我是程序员&#xff0c;我有权选择不关电脑。我需要在任何时候都能够…

C++一维数组

个人主页&#xff1a;PingdiGuo_guo 收录专栏&#xff1a;C干货专栏 铁汁们大家好呀&#xff0c;我是PingdiGuo_guo&#xff0c;今天我们来学习一下数组&#xff08;一维&#xff09;。 文章目录 1.数组的概念与思想 2.为什么要使用数组 3.数组的特性 4.数组的操作 1.定义…

0 代码自动化测试:RF 框架实现企业级 UI 自动化测试

前言 现在大家去找工作&#xff0c;反馈回来的基本上自动化测试都是刚需&#xff01;没有自动化测试技能&#xff0c;纯手工测试基本没有什么市场。 但是很多人怕代码&#xff0c;觉得自动化测试就需要代码&#xff01;代码学习起来很难&#xff01; 当然代码学习不难&#xf…