【极简动态规划Day four- 接雨水】|Java 刷题打卡

298 阅读3分钟

本文正在参加「Java主题月 - Java 刷题打卡」,详情查看<活动链接>

【Java 刷题打卡 】刷题比玩游戏好多了,成就感越来越强,每天坚持刷几道题,每天锻炼30分钟,等8块腹肌,等大厂offer.

那就干吧! 这个专栏都是刷的题目都是关于动态规划的,我会由浅入深、循序渐进,刷题就是这样需要连续不断的记忆--艾宾浩斯记忆法2121112。动态规划的内容不多,但是都是每个程序员必备的

这道题很经典啦😄😄😄 \color{green}{这道题很经典啦😄 😄 😄 ~}

刷题之路,任重而道远啊

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

1.计数

  • 有多少种方式走到右下角
  • 有多少种方法选出k个数是的和是sum

2.求最大值最小值

  • 从左上角走到右下角路径的最大数字和
  • 最长上升子序列长度

3.求存在性

  • 取石子游戏,先手是否必胜
  • 能不能选出k个数使得和是sum

题目一

leecode 42. 接雨水

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

421.jpg

输入: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字符结尾的最多的有效雨水

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

  • 最后一步
  • 子问题

最后一步

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

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

image.png

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

423.jpg

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

424.jpg

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

子问题

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

从重叠的图中可以看到最后一个位置的最小值为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 = {2, 0, 6, 1};
    int i = trap(candidates);
    Assert.assertNotNull(i);
}

真心感谢帅逼靓女们能看到这里,如果这个文章写得还不错,觉得有点东西的话

求点赞👍 求关注❤️ 求分享👥 对8块腹肌的我来说真的 非常有用!!!

如果本篇博客有任何错误,请批评指教,不胜感激 !❤️❤️❤️❤️