每日一算法题-接雨水问题

54 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第26天,点击查看活动详情

一、题目

描述:
给定一个整形数组arr,已知其中所有的值都是非负的,将这个数组看作一个柱子高度图,计算按此排列的柱子,下雨之后能接多少雨水。(数组以外的区域高度视为0)

image.png

输入: [3, 1, 2, 5, 2 ,4]
输出: 5

#include <iostream>
#include <vector>
using namespace std;

long long maxWater(vector<int>& water) {
}

int main(int, char*[])
{
    vector<int> water = {3, 1, 2, 5 ,2, 4};
    cout << maxWater(water) << endl;
}

二、分析

由题意可知,要获得接雨水的大小,就是获取这个容器的大小。
一个完整的容器必须保证两条竖边形成U字形,若中间有更高的柱子,就分割形成两个容器。
通过不断的分割,最终会形成若干个完整的容器。
而容器的大小由两条竖边的最短边与中间柱子形成空格多少决定。
这种背景下,容器的体积由最短边决定,而是否形成新容器由最长边决定。
通过不断的寻求最高柱子,就能知道每个容器的边界。
每次迭代时,求最短边与临边的空格,就能知道当前容器的体积。

三、模拟

  1. 3,1,2,5,2,4 短边为3,暂无边界,当前容器最小边界为3
  2. 1,2,5,2,4 短边为1,与边界形成2个空格,当前容器最小边界为3
  3. 2,5,2,4 短边为2,与边界形成1个空格,当前容器最小边界为3
  4. 5,2,4 短边为4,暂无边界,当前容器最小边界为4
  5. 5,2 短边为2,与边界形成2个空格,当前容器最小边界为4
  6. 5 结束

四、实现

long long maxWater(vector<int>& water) {
    if (water.empty())
        return 0;
    long long res = 0;
    int left = 0;
    int right = water.size() - 1;
    int maxL = 0;
    int maxR= 0;
    while(left < right) {
        maxL = max(maxL, water[left]);
        maxR = max(maxR, water[right]);
        if (maxR > maxL)
            res += maxL - water[left++];
        else
            res += maxR - water[right--];
    }
    return res;
}

五、结言

这道题也是对动态规划的考量,通过对容器的划分,不断求容器的大小来达到最终的目的。

创作不易,留个赞再走吧!如果对文章内容有任何指正,欢迎评论!