由于本人的算法基础较为薄弱,所以在这里整理一下自己的做过的题,使自己能够随时随地回顾温习。

然后,本篇文章将会持续更新自己遇到的一些比较经典动态规划的题目,大家如果对代码有任何问题,直接在文章下面评论即可。我看到后会立刻回复。

1.我对动态规划的理解

网上对动态规划的介绍的文章已经很多了,那这里我还是要谈一下自己的理解,希望能够给大家带来一些灵感。

我所理解的动态规划,就两个词:动态、规划。动态我自己理解为:一个问题可以拆分为若干个子问题,然后通过逐步递推,得到最终的结果。规划就是最优问题,整体的最优细分到每个递推环节的最优。

然后,解决动态规划问题,最重要的可以发现其中的状态转移方程,我理解的状态转移方程的意思就是:一个通用的方程,即任意中间一个状态能够由前面的状态所推导得到。比如下图的dp[i][j]状态,就可以由左上的3个状态推导得到。

很多动态规划的问题,具体解法大多都是通过一个二维数组来存储中间环节的最优解。最后求二维数组中的最大值或者最后一个值。还有一种情况就是:如果当前状态只跟前面的一个状态有关,那么二维数组是可以优化为一维数组的,这样空间复杂度就由O(n2)优化为O(n)了。

2.例题整理

2.1 经典01背包问题

题目描述:一个人去偷东西,他的背包容量最大为20kg,然后有重量、价值不等的物品,比如重量为2、价值为3的物品,每件物品只能拿一件,求小偷能偷到的物品最大的价值。

"""

物品重量与价值对应关系:

w v

2 3

3 4

5 8

9 10

背包容量:20

"""

import numpy as np

def func(pack, cap):

max_value_arr = np.zeros([len(pack)+1, cap+1])

# 第一列与第一排全为0,这样为后续能递推max_value_arr的值

max_value_arr[:,0] = 0

max_value_arr[0,:] = 0

# i代表pack物品的序号

for i in range(1, len(pack)+1):

# j代表包中剩余的空间

for j in range(1, cap+1):

# 第一种情况,包中剩余空间不足

if j < pack[i-1][0]:

max_value_arr[i, j] = max_value_arr[i-1, j]

# 第二种情况,包中空间足够

else:

# a代表放入当前物品后包中总价值,w是当前物品的所占空间

w = pack[i-1][0]

"""

下面这行是关键!!!为什么是i-1,这里必须用i-1才能推出当前的max_value_arr的值,

然后再加上单独的value

"""

a = max_value_arr[i-1, j-w] + pack[i-1][1]

# b代表不放当前物品包中的总价值,两者求最大值

b = max_value_arr[i-1, j]

max_value_arr[i, j] = max(a, b)

print(max_value_arr[-1, -1])

test_pack = [[2, 3],

[3, 4],

[4, 5],

[5, 8],

[9, 10]]

func(test_pack, 20)

2.2 最长公共子串

题目描述:a b两个字符串,求a b的最长公共子串。子串与子序列不同,子串必须是连续的,而子序列可以不连续。例如:

输入: a="abccbca",b="bccca"

输出: 3

解释: 最长公共子序列就是"bcc",为3

# 动态规划:只有当a[i-1]==b[j-1]时,子串长度才会在i-1与j-1的基础上+1

# 如果不同,则不变。用变量来记录表中最大的子串长度

a = "abccccdd"

b = "abcabcbbccs"

la = len(a)

lb = len(b)

res = [[0 for i in range(lb+1)] for j in range(la+1)]

mmax = 0

for i in range(1, la+1):

for j in range(1, lb+1):

if a[i-1] == b[j-1]:

res[i][j] = res[i-1][j-1] + 1

mmax = max(res[i][j], mmax)

print(mmax)

2.3 最长公共子序列(Leetcode1143)

题目描述:a b两个字符串,求a b的最长公共子序列。这里与上一题要区分开,重点是子序列可以是不连续的。

输入: a="abccbca",b="bccca"

输出: 6

解释: 最长公共子序列就是"bccca",为6

# 动态规划:相等就+1

# 如果不相等,则是max(a字符串少一个字符,b字符串少一个字符)

a = "abccccdd"

b = "abcabcbbcs"

la = len(a)

lb = len(b)

res = [[0 for i in range(lb+1)] for j in range(la+1)]

for i in range(1, la+1):

for j in range(1, lb+1):

if a[i-1] == b[j-1]:

res[i][j] = res[i-1][j-1] + 1

else:

res[i][j] = max(res[i-1][j], res[i][j-1])

print(res[-1][-1])

2.4 最大子序和(Leetcode53)

题目描述:给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。例如:

输入: [-2,1,-3,4,-1,2,1,-5,4],

输出: 6

解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

# 每项为:以此项为结尾的最大子序和

# 如果前一项的子序和<0,那么此项结尾的最大子序和就是本身

# 如果前一项的子序和>0,那么此项结尾的最大子序和就是前一项加上本身

def maxSubArray(nums):

l = len(nums)

res = [0 for i in range(l)]

for i in range(l):

if i == 0:

res[i] = nums[i]

else:

if res[i - 1] <= 0:

res[i] = nums[i]

else:

res[i] = nums[i] + res[i - 1]

return max(res)

2.5 最长上升子序列(Leetcode300)

题目描述:给定一个无序的整数数组,找到其中最长上升子序列的长度。例如:

输入: [10,9,2,5,3,7,101,18]

输出: 4

解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。

# 最长上升子序列(动态规划)

# res[i]代表以此项为结尾的最大上升子序列的长度

# 关键是,拿当前值nums[i]与前面的值nums[j]相对比

# 如果比它大,那么就可以在res[j]的基础上加1。最后判断遍历完nums前j个元素后,加一的最大值,作为res[i]

def lengthOfLIS(nums):

l = len(nums)

if l == 0:

return 0

res = [1 for i in range(l)]

for i in range(l):

max_ = 1

temp = 0

for j in range(i):

if nums[i] > nums[j]:

temp = res[j] + 1

if temp > max_:

max_ = temp

res[i] = max_

return res

nums = [10,9,2,5,3,7,101,1]

print(lengthOfLIS(nums))

# 2,3,7,101 max为4

2.6 摆动序列(Leetcode376)

题目描述:如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为摆动序列。第一个差(如果存在的话)可能是正数或负数。少于两个元素的序列也是摆动序列。

给定一个整数序列,返回作为摆动序列的最长子序列的长度。 通过从原始序列中删除一些(也可以不删除)元素来获得子序列,剩下的元素保持其原始顺序。例如:

输入: [1,17,5,10,13,15,10,5,16,8]

输出: 7

解释: 这个序列包含几个长度为 7 摆动序列,其中一个可为[1,17,10,13,10,16,8]。

# 这题分为,如果上一次的摆动时正时,那么如果此次为负摆动的时候,最长摆动序列为上一次的最长摆动序列加1,

# 如果此次为正摆动或者没有摆动时,最长摆动序列就是上一次的最长摆动序列数;如果上一次摆动为负时,那么

# 如果此次为正摆动的时候,最长摆动序列为上一次的最长摆动序列加1,如果此次为负摆动或者没有摆动时,最长

# 摆动序列就是上一次的最长摆动序列数。用数组来记录这些上一次的最长摆动序列,方便以后使用。

test_list = [1, 17, 3, 20, 15, 6, 7, 8]

def swing(test):

if len(test) < 2:

return len(test)

up = 1

down = 1

idx = 1

n = len(test)

while idx < n:

if test[idx] > test[idx-1]:

up = down + 1

if test[idx] < test[idx-1]:

down = up + 1

idx += 1

return max(up, down)

print(swing(test_list))

2.7 最小路径和(Leetcode64)

题目描述:给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。注意:每次只能向下或者向右移动一步。

这个题很常见,面试经常被问到。

输入:

[

[1,3,1],

[1,5,1],

[4,2,1]

]

输出: 7

解释: 因为路径 1→3→1→1→1 的总和最小。

def minPathSum(grid):

for i in range(len(grid)):

for j in range(len(grid[0])):

if i == j == 0:

continue

elif i == 0:

grid[i][j] = grid[i][j - 1] + grid[i][j]

elif j == 0:

grid[i][j] = grid[i - 1][j] + grid[i][j]

else:

grid[i][j] = min(grid[i - 1][j], grid[i][j - 1]) + grid[i][j]

return grid[-1][-1]

持续更新中……

python动态规划详解_经典动态规划例题整理(Python版)相关推荐

  1. 100行的python作品详解_不到 100 行 Python 代码徐峥变葛优

    给照片换脸大家应该都见过,本文我们来介绍一下如何通过 Python 实现换脸. 功能实现 实现换脸功能,我们大致可以分为两种:一种是所有功能都通过自己编码来实现,另一种是借助于第三方 API 来实现, ...

  2. python etree详解_使用lxml.etree解析python alexa结果

    您遇到两个挑战: >使用名称空间的XML >两个共享相同名称空间前缀的名称空间 具有两个不同名称空间重用前缀的XML文档 您会看到" aws:"前缀,但是它用于两个不同 ...

  3. 五大常用算法—动态规划详解和经典题目(python)

    一.基本概念    把多阶段过程转化为一系列单阶段问题,利用各阶段之间的关系,逐个求解.     动态规划过程:每次决策依赖于当前状态,又随即引起状态的转移.一个决策序列就是在变化的状态中产生出来的, ...

  4. 超详细!动态规划详解分析(典型例题分析和对比,附源码)

    为啥要使用动态规划?什么时候使用动态规划?以下是我的一些理解和心得,如果你感兴趣,就接着往下看吧. 对您有帮助的话记得给我点个赞哟! 动态规划的基本思想 动态规划(Dynamic Programmin ...

  5. python argv 详解_对python中的argv和argc使用详解

    主要问题 为什么argv中第一个,即index=0的内容就是文件名? python中argc是用什么实现的? 概念解释 argc:argument counter,命令行参数个数 argv:argum ...

  6. python学习详解_深入解析Python小白学习【操作列表】

    1.遍历列表 需要对列表中的每个元素都执行相同的操作时,可使用for 循环: magicians = ['alice','david','carolina'] for magician in magi ...

  7. python的抽象类详解_第7.19节 Python中的抽象类详解:abstractmethod、abc与真实子类...

    第7.19节 Python中的抽象类详解:abstractmethod.abc与真实子类 一. 引言 前面相关的章节已经介绍过,Python中定义某种类型是以实现了该类型对应的协议为标准的,而不是以继 ...

  8. python凯撒密码详解_四十八、Python用smtp发邮件详解(163和QQ邮箱)

    Python发邮件详解 一.利用163的smtp发送邮件 import smtplibfrom email.mime.text import MIMETextfrom email.header imp ...

  9. python跳一跳脚本详解_微信跳一跳游戏 python脚本辅助得高分

    微信小程序一时间火爆朋友圈,关键是还有排行榜!游戏操作简单,可直接根据电脑识别,用python写出自动跳辅助脚本,本想动手写下,索性网上有大神写了现成脚本,修改了一小部分参数,就可以稳定使用了霸榜没有 ...

最新文章

  1. 解题报告(十三)中国剩余定理(ACM / OI)
  2. 计算机语言中display翻译,display的意思在线翻译,解释display中文英文含义,短语词组,音标读音,例句,词源,同义词,反义词【澳典网ODict.Net】...
  3. Linux服务器上的oracle数据导入和导出
  4. Python随机数生成方法
  5. invoke 按钮点击_h5+ app内点击按钮实现复制功能 实现方法
  6. 可近似看作直线的是_高中物理题根之一:《匀变速直线运动的规律》
  7. Linux IO控制命令生成
  8. Densenet论文解读 深度学习领域论文分析博主
  9. 快速打开 Mac OS X 隐藏的用户资源库文件夹
  10. 3D重建模的初步了解
  11. GPS、基站、IP定位的区别及其应用方向
  12. justauth对接facebook、linkedin、twitter登陆
  13. Mybatis中文文档下载地址分享
  14. 耳机降噪功能(ANC、ENC、CVC、DSP)
  15. 分享抖音上热门技巧!短视频涨粉+运营攻略!
  16. 如何完全卸载删除Parallels Desktop Mac教程
  17. java当单据变化触发,UAP开发(NC63)遇到的错误记录
  18. 【雨滴降落的速度是每秒10米】
  19. 【转】Google Earth究竟是怎样工作的
  20. 弹指间计算机协会 2021“千里码”程序设计竞赛 题面

热门文章

  1. 用于自动泊车的鸟瞰图的边缘线的语义SLAM系统
  2. 数字太大了,计算加法、减法会报错,结果不正确?怎么办?用JavaScript实现大数据(超过20位的数字)相加减运算。
  3. 双重指针作为函数参数的妙用
  4. l-logger命令基本介绍
  5. 剑指offer-----Python-----栈
  6. 软件安装(ubuntu) --Linux基础编程
  7. linux命令find命令详解
  8. Linux篇---ftp服务器的搭建
  9. leetcode第一刷_Recover Binary Search Tree
  10. nginx基于IP的虚拟主机