Leetcode——Trapping Rain Water

题目描述

Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it is able to trap after raining.

给出n个非负整数,表示一个立面图,每一个条形图的宽度是1,计算下雨之后这个条形图能够存多少水

在这里插入图片描述

The above elevation map is represented by array [0,1,0,2,1,0,1,3,2,1,2,1]. In this case, 6 units of rain water (blue section) are being trapped.

上面那个立面图是用一组数组[0,1,0,2,1,0,1,3,2,1,2,1].在这个情况下,6个单元的雨水被填满。

思路分析

  • 来源:由简入繁的思路去探讨解题思路,由最初的只有三条线,变为后来的四条线,然后再变为后来的五条线,直到最后
  • 方法一:间距扫描,将start定在某个点,然后让end从start的位置开始出发,扫描所有的点,知道遇到第一个等于或者大于start的线,开始计算面积。
    • 问题:如果start定位的数线比较高,end直接到达末尾都没有找到比其高的竖线,就结束循环,中间的面积就没有计算,造成右部侧漏。
  • 方法二:找到所有的极大值,两个极大值之间一定形成了凹谷,然后计算面积
    • 问题:这完全是没有的任何作用的,只是讲问题简化了,并没有解决问题
  • 方法三:结合前面两种方法。找出最大值,分别从最大值的左右两侧向最大值进行遍历。用最大值当做最高墙,防止左右侧漏。

我的代码

#include <stdio.h>
#include <stdlib.h>

int trap(int *height,int heightSize);

int main()
{
    
    
    //今日份leetcode
    int p[] = {
    
    0,1,0,2,1,0,1,3,2,1,2,1};
    printf("%d \n",trap(p,12));
    return 0;
}
int trap(int *height, int heightSize)
{
    
    
    int container = 0;  //表示该条件下雨水的体积
    int start = 0;  //间距扫描的开始端
    int end = 1;    //间距扫描的结束端
    int obstacle = 0;   //计算障碍物的体积
    int maxIndex = 0;
    //判定直接返回0的情况
    if(heightSize < 3)
    {
    
    
        return 0;
    }
	//找到最高墙,防止侧漏
    for(int i = 0 ;i < heightSize;i++)
    {
    
    
        if(height[i] > height[maxIndex])
        {
    
    
            maxIndex = i;
        }
    }
    //从最高墙的左侧开始遍历
    while(start <= maxIndex && end <= maxIndex)
    {
    
    
        if(height[start] > height[end])
        {
    
    
            obstacle += height[end];
        }
        else
        {
    
    
            container = container + height[start] * (end - start - 1) - obstacle;
            obstacle = 0;
            start = end;
        }
        end ++;
    }
    start = heightSize - 1,end = start - 1,obstacle = 0;
   	//从最高墙的右侧开始遍历
    while(start >= maxIndex && end >= maxIndex)
    {
    
    
        if(height[start] > height[end])
        {
    
    
            obstacle += height[end];
        }
        else
        {
    
    
            container = container + height[start] * (start - end - 1) - obstacle;
            obstacle = 0;
            start = end;
        }
        end --;
    }
    return container;
}

分析与总结

  • 既然已经简化了问题,从仅仅有三条线进行考虑,那就会出现好几种情况,我没有完全考虑到这些情况。仅仅是得到了一种问题解答便结束思考。需要改正。

借鉴——Terrible Whiteboard在YouTuBe上传的视频

双向遍历,两线相减

在这里插入图片描述

在这里插入图片描述

  • 从左往右进行一次扫描和从右向左进行扫描,分别生成了两个数组,然后进行依次取最小值,再减去底部的建筑的面积,得到对应的水的面积。

代码实现

int trap(vector<int>& height)
{
    
    
	if(height == null)
		return 0;
    int ans = 0;
    int size = height.size();
    vector<int> left_max(size), right_max(size);
    left_max[0] = height[0];
    for (int i = 1; i < size; i++) {
    
    
        left_max[i] = 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] = max(height[i], right_max[i + 1]);
    }
    for (int i = 1; i < size - 1; i++) {
    
    
        ans += min(left_max[i], right_max[i]) - height[i];
    }
    return ans;
}
暴力破解brute force
  • 逐步遍历所有的元素,对每一个元素i重复一下的操作:
    • 从当前元素向左遍历找最大的元素MAX_LEFT
    • 从当前元素向右遍历找最大的元素MAX_RIGHT
    • 在MAX_LEFT和MAX_RIGHT中找较小的那个值min
    • 然后用min减去当前的值i,并将所有的值进行累加,即为最终答案

猜你喜欢

转载自blog.csdn.net/Blackoutdragon/article/details/108184197