大家好!

动态规划题目是总结的比较完整了。下面是自从和大家刷开题总结的动态规划解题方法。

今年全国夏天雨是真的多,突然想到今年北京的夏天也不像往年那么热。不知不觉就稳稳地度过了夏天来到秋天。

恰巧前几天有一个粉丝问到了我,网上接雨水的解决总是感觉有点混乱,能不能用动态规划解决。

今早北京大雨,借用大雨的感受,想了想接雨水问题,依然用长图一步一步说明!

背景

先来看看题目,这个题目应该是很多人都已经遇到过了,因为它的题号是42,属于一个比较非常靠前的题目。

同时也属于一个非常经典的算法问题。

咱们今天的题目解决不做暴力法、也不做双指针,就用动态规划很清晰的进行说明。

看下图,12根柱子的围栏,接了6个单位的雨水。

从上图很显然能看到一点:

如果想要接住雨水。那么,决定雨量的多少在于「左边的柱子高度」、「右边的柱子高度」以及「自身柱子的高度」。

比如说,中间第 5 格雨水量为2,就是决定于左右侧柱子的较小值-本身柱子高度(0)而得到的。

注意:左右侧的高度,指的是能围住雨水的柱子,而不是紧挨着的左右侧的柱子。

左侧最高柱子:2

右侧最高柱子:3

自身柱子高度:0

雨水量 = min(左侧最高柱子, 右侧最高柱子) - 自身柱子高度 = 2

因此,需要定义两个数组,分别来存放相对于当前位置左侧和右侧柱子的最大高度。

最后,取左右侧柱子最小值-自身柱子高度=雨水量。

思路

就用leetcode官方给的案例来进行一步一步解决。

柱子高度为:height = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1],再把图拿过来!

现在,定义两个数组,分别命名为 left_max_height right_max_height,存放相对于当前位置左侧和右侧柱子的最大高度。

先来定义第一个数组left_max_height,存放左侧最高柱子高度:

初始化:(因为左侧没有柱子,所以位置 0 左侧最大高度为 0)

  1. left_max_height[0] = 0

动态方程:

  1. left_max_height[i]=max(height[i-1], left_max_height[i-1])

下面还是用长图一步一步来进行说明:【点击高清显示】

下面开始定义第二个数组,存放右侧最高柱子高度。右侧最高度从最右侧开始进行计算。

初始化:(因为最后一个位置由侧没有柱子,所以位置 11 右侧最大高度为 0)

  1. right_max_height[11] = 0

动态方程:

  1. right_max_height[j]=max(height[j+1], right_max_height[j+1])

还是用长图一步一步来进行说明:【点击高清显示】

现在,当前位置的左侧和右侧柱子的最大高度数组计算完成后,下面就计算接水量。

雨水量 = min(左侧最高柱子, 右侧最高柱子) - 自身柱子高度 = 2

准备好三个数组:

上图中,height = [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1],为了看起来清晰,可以参考最开始图示。

最大单位水量=左右取最小值-本身的高度

计算方式:

  1. water=min(left_max_height[i], right_max_height[i])-height[i])
  2. max_water=water>=0?water:0

上述需要注意一点,如果左右取最小值-本身的高度<0,说明当前本身柱子是凸出来左右侧最高值的,比如说位置 1:

所以说,位置 1 的计算结果为负数,需要强制转为 0。

代码

  1. class Solution(object):
  2. def trap(self, height):
  3. size = len(height)
  4. # 小于等于 2 的时候,是接不住雨水的
  5. if size <= 2:
  6. return 0
  7. # 左边相对于当前位置的最大高度
  8. left_max_height = [0 for _ in range(size)]
  9. # 右边相对于当前位置的最大高度
  10. right_max_height = [0 for _ in range(size)]
  11. # 当前位置接雨水最大高度
  12. max_water = [0 for _ in range(size)]
  13. # 初始化 left_max_height, 第 0 个位置初始化为 0
  14. for i in range(1, size):
  15. left_max_height[i] = max(height[i-1], left_max_height[i-1])
  16. # 初始化 right_max_height, 第 size-1 个位置初始化为 0
  17. for j in range(1, size):
  18. right_max_height[size-j-1] = max(height[size-j], right_max_height[size-j])
  19. # 最大水量
  20. for k in range(1, size):
  21. max_water[k] = (min(left_max_height[k], right_max_height[k])-height[k] if min(left_max_height[k], right_max_height[k])-height[k]>=0 else 0)
  22. # 累计求单位水量
  23. waters = 0
  24. for z in range(1, size):
  25. waters += max_water[z]
  26. return waters
  27. if __name__ == '__main__':
  28. s = Solution()
  29. print(s.trap([0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1]))

这个题目总体来说,使用动态规划还是不容易想到的。尤其是上面两个数组使用了两次动态规划的过程。

接雨水问题还可以使用暴力解法和双指针解决,双指针可以试试,至于暴力。。心里有就好了哈哈。。

多余的一句

边工作边带大家刷题确实是有点慢了,很抱歉!

不过,一定会坚持下去,也一定会把 LeetCode 各类型题目进行详细总结,做到大家想查看的时候随时能查到详细 LeetCode 资料的地方。

另外,方便的话也在我的github 加颗星,它是我持续输出最大最大的动力,感谢大家!

github:https://github.com/xiaozhutec/share_leetcode

【完虐算法】LeetCode 接雨水问题,全复盘的更多相关文章

  1. 前端与算法 leetcode 26. 删除排序数组中的重复项

    目录 # 前端与算法 leetcode 26. 删除排序数组中的重复项 题目描述 概要 提示 解析 算法 # 前端与算法 leetcode 26. 删除排序数组中的重复项 题目描述 26. 删除排序数 ...

  2. 前端与算法 leetcode 350. 两个数组的交集 II

    目录 # 前端与算法 leetcode 350. 两个数组的交集 II 题目描述 概要 提示 解析 解法一:哈希表 解法二:双指针 解法三:暴力法 算法 # 前端与算法 leetcode 350. 两 ...

  3. 前端与算法 leetcode 283. 移动零

    目录 # 前端与算法 leetcode 283. 移动零 题目描述 概要 提示 解析 解法一:暴力法 解法二:双指针法 算法 传入[0,1,0,3,12]的运行结果 执行结果 GitHub仓库 # 前 ...

  4. 前端与算法 leetcode 1. 两数之和

    目录 # 前端与算法 leetcode 1. 两数之和 题目描述 概要 提示 解析 解法一:暴力法 解法二:HashMap法 算法 传入[1, 2], [11, 1, 2, 3, 2]的运行结果 执行 ...

  5. 前端与算法 leetcode 48. 旋转图像

    目录 # 前端与算法 leetcode 48. 旋转图像 题目描述 概要 提示 解析 解法一:转置加翻转 解法二:在单次循环中旋转 4 个矩形 算法 传入测试用例的运行结果 执行结果 GitHub仓库 ...

  6. 前端与算法 leetcode 7. 整数反转

    目录 # 前端与算法 leetcode 7. 整数反转 题目描述 概要 提示 解析 解法 算法 传入测试用例的运行结果 执行结果 GitHub仓库 # 前端与算法 leetcode 7. 整数反转 题 ...

  7. 前端与算法 leetcode 8. 字符串转换整数 (atoi)

    目录 # 前端与算法 leetcode 8. 字符串转换整数 (atoi) 题目描述 概要 提示 解析 解法一:正则 解法二:api 解法二:手搓一个api 算法 传入测试用例的运行结果 执行结果 G ...

  8. 前端与算法 leetcode 387. 字符串中的第一个唯一字符

    目录 # 前端与算法 leetcode 387. 字符串中的第一个唯一字符 题目描述 概要 提示 解析 解法一:双循环 解法二:Set法单循环 算法 传入测试用例的运行结果 执行结果 GitHub仓库 ...

  9. 前端与算法 leetcode 125. 验证回文串

    目录 # 前端与算法 leetcode 125. 验证回文串 题目描述 概要 提示 解析 解法一:api侠 解法二:双指针 算法 传入测试用例的运行结果 执行结果 GitHub仓库 查看更多 # 前端 ...

随机推荐

  1. 鸿蒙内核源码分析(内存管理篇) | 虚拟内存全景图是怎样的 | 百篇博客分析OpenHarmony源码 | v12.04

    百篇博客系列篇.本篇为: v12.xx 鸿蒙内核源码分析(内存管理篇) | 虚拟内存全景图是怎样的 | 51.c.h .o 内存管理相关篇为: v11.xx 鸿蒙内核源码分析(内存分配篇) | 内存有 ...

  2. P6295-有标号 DAG 计数【多项式求逆,多项式ln】

    正题 题目链接:https://www.luogu.com.cn/problem/P6295 题目大意 求所有\(n\)个点的弱联通\(DAG\)数量. \(1\leq n\leq 10^5\) 解题 ...

  3. Python中open和with open有什么区别?怎么用?

    open 打开文件 file=open("文件名","读写模式") 操作文件 代码段 关闭文件 file.close() 注意事项:使用open方法,文件操作完 ...

  4. python OSError: [Errno 22] Invalid argument: '\u202aF://text

    windows10 python3 读文件的时候报的错误 原因不明时好时坏很头疼但又没办法不知道怎么解决,网上的说法都不能解决,

  5. Cnblogs 主题设置

    https://www.cnblogs.com/enjoy233/p/cnblogs-markdown-code-display-opt.html 复制: 右上角添加复制按钮:https://www. ...

  6. 产生UUID随机字符串工具类

    产生UUID随机字符串工具类 UUID是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的.通常平台会提供生成的API.按照开放软件基金会(OSF)制定的标准计算,用到了以太网卡地址. ...

  7. Python Pandas的使用 !!!!!详解

     Pandas是一个基于python中Numpy模块的一个模块 Python在数据处理和准备⽅⾯⼀直做得很好,但在数据分析和建模⽅⾯就差⼀些.pandas帮助填补了这⼀空⽩,使您能够在Python中执 ...

  8. HTML5元素背景知识

    目录 HTML5元素背景知识 语义与呈现分离 元素选用原则 少亦可为多 别误用元素 具体为佳,一以贯之 对用户不要想当然 元素说明体例 ol元素 元素速览 文档和元数据元素 文档和元数据元素 文本元素 ...

  9. Python内置高阶函数map()

    map()函数map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回. 例如,对于lis ...

  10. struts2漏洞复现分析合集

    struts2漏洞复现合集 环境准备 tomcat安装 漏洞代码取自vulhub,使用idea进行远程调试 struts2远程调试 catalina.bat jpda start 开启debug模式, ...