【动态规划Day four- 接雨水】

可紊 提交于 2021-02-14 13:57:21

点蓝色字关注“汀雨笔记”

有矛盾正是生机蓬勃的象征。




本文旨在记录一些关于dp的训练题,如果你对动态规划不熟悉,望转到该篇

----

我是怎么向5岁侄女解释动态规划的?

----

刷题之路,任重而道远啊


什么题可以选择动态规划来做?

1.计数

  • 有多少种方式走到右下角

  • 有多少种方法选出k个数是的和是sum

2.求最大值最小值

  • 从左上角走到右下角路径的最大数字和

  • 最长上升子序列长度

3.求存在性

  • 取石子游戏,先手是否必胜

  • 能不能选出k个数使得和是sum



题目一


leecode 42. 接雨水

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。


 




输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]

输出:6

解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。 

示例 2:


输入:height = [4,2,0,3,2,5]

输出:9

 


提示:


n == height.length

0 <= n <= 3 * 104

0 <= height[i] <= 105


看了之前的文章,我们就四步走吧

这道题相对而言,提升了难度,常规的题,我们的计算顺序一般是从左到右,或者从右到左,亦或是从上到下。


1.1. 动态规划组成部分1:确定状态


简单的说,解动态规划的时候需要开一个数组,数组的每个元素f[i]或者f[i][j]代表什么,类似数学题x, y, z代表什么


wc,你倒是说说怎么确定要用动态规划来做啊?

  • 看题目,需要逐步验证最长长度

  • 没有时间复杂度空间复杂度限制,你可以选择>=On的

  • 跟前面题很类似,这里需要考虑每一步最高的高度取低位高度,因为可能形成低洼

  • 尝试根据步骤写出转移方程


在这道题中,我们定义d[i]表示以下标  i 字符结尾的最多的有效雨水


解动态规划需要两个意识:

  • 最后一步

  • 子问题


最后一步


我们可以利用填满法来降低复杂度。去掉低洼的情况。


先从左到右来看,求出每个位置的最大高度(深度)




从右往左看,求出每个位置的最大高度



我们在来看它们重叠之后的效果



这样每个位置的最小值 - 高度就是每个位置的蓄水值。


子问题



我们存储了从左到右和从右到左每个位置的最大值

从重叠的图中可以看到最后一个位置的最小值为2,减去高度,蓄水值为0.



1.2. 动态规划组成部分2:转移方程


 ans += Math.min(left_max[i], right_max[i]) - height[i];



1.3. 动态规划组成部分3:初始条件和边界情况 



1.4. 动态规划组成部分4:计算顺序


从左到右 + 从右到左


它的时间复杂度是On,空间复杂度也是On


当然也有其他的解决办法如栈


参考代码


public int trap(int[] height) {
    if (height == null || height.length == 0)
        return 0;
    int ans = 0;
    int size = height.length;
    int[] left_max = new int[size];
    int[] right_max = new int[size];
    left_max[0] = height[0];
    for (int i = 1; i < size; i++) {
        left_max[i] = Math.max(height[i], left_max[i - 1]);
    }
    right_max[size - 1] = height[size - 1];
    for (int i = size - 2; i >= 0; i--) {
        right_max[i] = Math.max(height[i], right_max[i + 1]);
    }
    for (int i = 1; i < size - 1; i++) {
        ans += Math.min(left_max[i], right_max[i]) - height[i];
    }
    return ans;
}

@Test
public void istrap() {
    int[] candidates = {2061};
    int i = trap(candidates);
    Assert.assertNotNull(i);
}



热门推荐:



   
   
   

扫码关注公众号

精彩内容早知道


文末福利,最近整理一份面试资料Java面试通关手册,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。

获取方式:点“在看”,关注公众号并回复 interview 领取,更多内容陆续奉上。



本文分享自微信公众号 - 汀雨笔记(anni_zhouJ)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!