【leetcode刷题】--- 我遇到一道很坏很坏的题~

前言
作者简介:大家好,我是翼同学
个人主页:翼同学的CSDN博客
系列专栏:【Leetcode】刷题与总结
备注:如果文章有误,请指正,万分感谢!让我们一起学习,一起进步。
✅最后:如果文章对您有帮助,请三连支持一下博主哦。

目录

  • 前言
  • 题目
  • 普通解法
    • 思路一
    • 思路二
  • 其他解法
    • 思路三
    • 思路四
  • 写在最后


前言

今天在Leetcode上刷题,看到一道题很有趣。我乍一看,没有思路,但是仔细想了想,还是没思路。。。。哈哈,开个玩笑。

当我写出后解法后,系统老是提醒超出时间限制,太难了,努力想了好久,优化解法后终于通过了!还挺有成就感。

后来在官方的解法中,我又学到了其他的解题方法,解题的思路非常棒,所以就有了这篇文章,想和大家分享一下。

【leetcode刷题】--- 我遇到一道很坏很坏的题~_第1张图片


题目

描述:

  • 给定一个数组height,数组里有 n非负整数

  • 每个元素都表示一个宽度为 1 的柱子的高度

  • 现在让我们来计算按此排列的柱子,下雨之后能接多少雨水。

例如:

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

✔️示意图:

【leetcode刷题】--- 我遇到一道很坏很坏的题~_第2张图片

解释:

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

普通解法

思路一

  • 刚开始我的想法是,只要求出每一列上能存放的雨水量,再加起来就行
  • 需要注意的是,最两端的柱子是不用考虑的,因为也不可能有雨水
  • 下面举两个例子来解释一下我的思路

举例一:
【leetcode刷题】--- 我遇到一道很坏很坏的题~_第3张图片

由上图可知,若想求A列上的雨水,则可发现:

  • A两侧最高的列分别是BC
  • 显然BC
  • 那么A上接到的雨水量为B-A
  • 也就是说,A上的雨水量为2

举例二:

【leetcode刷题】--- 我遇到一道很坏很坏的题~_第4张图片

由上图可知,若想求A列上的雨水,则可发现:

  • A两侧最高的列分别是BC
  • 显然BC
  • 但是此时的BA还要矮
  • 那么A上并不能接到雨水

总结:

  • 我们可以对每一列上的雨水量进行计算(最两端的柱子不考虑),最后相加即可。

  • 需要遍历数组,对每一列A的左右两侧BC中,取出较矮的那一列,减去A列的高度就能求出A上接到的雨水量(如例子一

  • 但是如果B,C较矮的那一列比A还要矮,那么A上就没有雨水。(如例子二

代码

这是刚开始我写的代码

【leetcode刷题】--- 我遇到一道很坏很坏的题~_第5张图片

但是超出了时间限制:

【leetcode刷题】--- 我遇到一道很坏很坏的题~_第6张图片

虽然这个思路不错,但是太耗时间了,通过不了。

那怎样能减低时间复杂度?

当我们分析后发现,上述代码之所以时间复杂度高,是因为对于计算每一列上的雨水量,都必须向两边寻找最大值,这就很耗费时间。

但是,我们可以利用动态规划,先知道每个位置的两侧的最大值是多少,那么就能够更加快速的求出接到的雨水量。也就是说,提前储存每个位置上左边所有柱子中的最大值,以及右边所有柱子中的最大值。

这该如何实现呢?

思路如下:

  • 我们可以定义两个数组BC
  • 1 <= i <= n-1时,在B[i]表示下标i及其i左边的柱子中的最大值
  • 正向遍历数组height,得到B[]
  • 0 <= j <= n-2时,在C[j]表示下标j及其j右边的柱子中的最大值
  • 反向遍历数组height,得到C[]
  • 最后遍历数组height,对于每个柱子,计算接到的雨水值,和之前那个超时的算法差不多

【leetcode刷题】--- 我遇到一道很坏很坏的题~_第7张图片

很幸运!通过了。

【leetcode刷题】--- 我遇到一道很坏很坏的题~_第8张图片

那么问题来了,还能想到什么解法呢?

想了很久后,思路二出现了。


思路二

看下图:

【leetcode刷题】--- 我遇到一道很坏很坏的题~_第9张图片

  • 我们先找出数组中柱子高度的最大值。
  • 然后乘以数组的大小,得到了一个长方形。
  • 求出这个长方形的面积后,减去白色部分和黑色部分的面积后,就可以得到雨水量!

所以整理一下思路

写出代码如下:

【leetcode刷题】--- 我遇到一道很坏很坏的题~_第10张图片

通过了!

【leetcode刷题】--- 我遇到一道很坏很坏的题~_第11张图片


其他解法

接下来,我们来欣赏一下其他超棒的解法!

思路三

思路三是利用单调栈的思想。

下面是来自LeetCode官方题解:

【leetcode刷题】--- 我遇到一道很坏很坏的题~_第12张图片

【leetcode刷题】--- 我遇到一道很坏很坏的题~_第13张图片

代码实现如下:

【leetcode刷题】--- 我遇到一道很坏很坏的题~_第14张图片

思路四

思路四是利用双指针的思想。

同样也是官方的解法。

具体如下:

【leetcode刷题】--- 我遇到一道很坏很坏的题~_第15张图片

【leetcode刷题】--- 我遇到一道很坏很坏的题~_第16张图片

【leetcode刷题】--- 我遇到一道很坏很坏的题~_第17张图片


写在最后

说实话,遇到这道很坏很坏的题,确实体会到很多,其中一点就是我好菜。。。

随着刷题次数增加后,当我回过头来看今天记录的这道难题,希望能够更加轻松,彻底的理解与掌握。

对于这道题,你有什么想法呢,欢迎到评论区一起讨论,分享你的解法吧!!!

你可能感兴趣的:(【Leetcode】刷题与总结,学习,c++,后端,刷题)