字节员工是不是个个都会接雨水。。

6623753a06e54321597d98214abab7f1.gif

(关注数据结构和算法,了解更多新知识)

最近一网友问到:字节的是不是都会接雨水,这里说的接雨水实际上是LeetCode上的一道算法题,因为这题在LeetCode上的难度为困难,并且又是字节常考的一道题,所以该网友才会这样问。

c832a73b0a5166d37b561961293a7054.png

我们来看下其他网友的回复,甚至有的网友调侃连保洁阿姨都会,从大家的评论中我们可以看到,实际上这题不算太难。

1585547c01480b9f6a7d82c06c1ca4c1.png

dbba7ceefa0fbd26515e83dcd0b9992b.png

e75797172db1ebfa968f36910962c695.png

f3d3ac25faf1c2cd7813b56bba0898f0.png

c4cf37d05b2d468268eeedd8f2472a24.png

086e0befa613dbd2aa2da7da060f5c57.png

caf7e3d6634304fd3282f4754c47fef4.png

098c48a3734a52ab3f6db3b58d8a3a5a.png

637c15330d16519f8d8845cfb60a584a.png

问题描述

来源:LeetCode第42题

难度:困难

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

示例1:

15aeebf031e07d5d758b658d35dbd2e1.png

输入: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

  • 1 <= n <= 2 * 10^4

  • 0 <= height[i] <= 10^5

问题分析

这题解法比较多,可以使用双指针,单调栈以及动态规划来解决。我们这里只介绍其中的一种,看一下动态规划的解决方式。

首先从左往右遍历数组,记录每一个位置左边(包含自己)的最大值,然后再从右往左遍历数组,记录每一个位置右边(包含自己)的最大值。

两次遍历完之后我们就知道每一个位置左边和右边的最大值了,左右两边的最大值围成的区域可以看作是一个桶,桶的高度取决于这两个值的最小值,知道桶的高度就可以计算当前位置所能容纳的水了,最后只需要计算所有位置容纳的水量即可。

JAVA:

public int trap(int[] height) {
    int length = height.length;
    int[] leftMax = new int[length];
    leftMax[0] = height[0];
    for (int i = 1; i < length; ++i)// 计算左边的最大值
        leftMax[i] = Math.max(leftMax[i - 1], height[i]);

    int[] rightMax = new int[length];
    rightMax[length - 1] = height[length - 1];
    for (int i = length - 2; i >= 0; --i)// 计算右边的最大值
        rightMax[i] = Math.max(rightMax[i + 1], height[i]);

    // 根据左右两边的最大值来确定当前柱子所能容纳的水量。
    int water = 0;
    for (int i = 0; i < length; ++i)
        water += Math.min(leftMax[i], rightMax[i]) - height[i];
    return water;
}

C++:

public:
    int trap(vector<int> &height) {
        int length = height.size();
        int leftMax[length];
        leftMax[0] = height[0];
        for (int i = 1; i < length; ++i)// 计算左边的最大值
            leftMax[i] = max(leftMax[i - 1], height[i]);

        int rightMax[length];
        rightMax[length - 1] = height[length - 1];
        for (int i = length - 2; i >= 0; --i)// 计算右边的最大值
            rightMax[i] = max(rightMax[i + 1], height[i]);

        // 根据左右两边的最大值来确定当前柱子所能容纳的水量。
        int water = 0;
        for (int i = 0; i < length; ++i)
            water += min(leftMax[i], rightMax[i]) - height[i];
        return water;
    }

C:

int trap(int *height, int heightSize) {
    int leftMax[heightSize];
    leftMax[0] = height[0];
    for (int i = 1; i < heightSize; ++i)// 计算左边的最大值
        leftMax[i] = fmax(leftMax[i - 1], height[i]);

    int rightMax[heightSize];
    rightMax[heightSize - 1] = height[heightSize - 1];
    for (int i = heightSize - 2; i >= 0; --i)// 计算右边的最大值
        rightMax[i] = fmax(rightMax[i + 1], height[i]);

    // 根据左右两边的最大值来确定当前柱子所能容纳的水量。
    int water = 0;
    for (int i = 0; i < heightSize; ++i)
        water += fmin(leftMax[i], rightMax[i]) - height[i];
    return water;
}

Python:

def trap(self, height: List[int]) -> int:
    length = len(height)
    leftMax = [0] * length
    leftMax[0] = height[0]
    for i in range(1, length):  # 计算左边的最大值
        leftMax[i] = max(leftMax[i - 1], height[i])

    rightMax = [0] * length
    rightMax[length - 1] = height[length - 1]
    for i in range(length - 2, -1, -1):  # 计算右边的最大值
        rightMax[i] = max(rightMax[i + 1], height[i])

    # 根据左右两边的最大值来确定当前柱子所能容纳的水量。
    water = 0
    for i in range(0, length):
        water += min(leftMax[i], rightMax[i]) - height[i]
    return water

693d5b0edc579282cb1a39f72f42585f.gif

笔者简介

博哥,真名:王一博,毕业十多年,《算法秘籍》作者,专注于数据结构和算法的讲解,在全球30多个算法网站中累计做题2000多道,在公众号中写算法题解800多题,对算法题有自己独特的解题思路和解题技巧,喜欢的可以给个关注,也可以下载我整理的1000多页的PDF算法文档。

  • 19
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。在编写C程序时,需要注意变量的声明和定义、指针的使用、内存的分配与释放等问题。C语言中常用的数据结构包括: 1. 数组:一种存储同类型数据的结构,可以进行索引访问和修改。 2. 链表:一种存储不同类型数据的结构,每个节点包含数据和指向下一个节点的指针。 3. 栈:一种后进先出(LIFO)的数据结构,可以通过压入(push)和弹出(pop)操作进行数据的存储和取出。 4. 队列:一种先进先出(FIFO)的数据结构,可以通过入队(enqueue)和出队(dequeue)操作进行数据的存储和取出。 5. 树:一种存储具有父子关系的数据结构,可以通过中序遍历、前序遍历和后序遍历等方式进行数据的访问和修改。 6. 图:一种存储具有节点和边关系的数据结构,可以通过广度优先搜索、深度优先搜索等方式进行数据的访问和修改。 这些数据结构在C语言中都有相应的实现方式,可以应用于各种不同的场景。C语言中的各种数据结构都有其优缺点,下面列举一些常见的数据结构的优缺点: 数组: 优点:访问和修改元素的速度非常快,适用于需要频繁读取和修改数据的场合。 缺点:数组的长度是固定的,不适合存储大小不固定的动态数据,另外数组在内存中是连续分配的,当数组较大时可能会导致内存碎片化。 链表: 优点:可以方便地插入和删除元素,适用于需要频繁插入和删除数据的场合。 缺点:访问和修改元素的速度相对较慢,因为需要遍历链表找到指定的节点。 栈: 优点:后进先出(LIFO)的特性使得栈在处理递归和括号匹配等问题时非常方便。 缺点:栈的空间有限,当数据量较大时可能会导致栈溢出。 队列: 优点:先进先出(FIFO)的特性使得

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

数据结构和算法

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值