LeetCode Algorithms 42. Trapping Rain Water

来源:互联网 发布:巨人网络 2017财报 编辑:程序博客网 时间:2024/06/14 10:46

题目难度: Hard


原题描述:

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.

For example,
Given [0,1,0,2,1,0,1,3,2,1,2,1], return 6.



题目大意:

        有n条长木块,每条木块的宽度均为1,高度为题目给出的数组中的非负整数。问在这些木块组成的图形之中加水,最多能加多大体积的水?


解题思路:

        一开始对着题目给出的图来想,想错了,以为可以把题目的输入划分成一个个“U”型的部分,即每一部分都是先下降后上升,然后再求每一部分能装水的体积,最后加起来。但是这种方法是不行的,如果有多个“U”连起来且最左和最右都是最高的木块,这样能装水的体积就不止这么少了。

      后来再想才找到了正确的算法。每一次在数组中找两个最大的数,如果有多个相同,则任取一个。假设左边的数是a,右边的数是b,则在a和b之间的数就可以调用getPartWater()函数来计算在这两个数之间能装水的最大值。接着分别对a左边的数和b右边的数递归调用本函数,来获得这两部分能装水的最大值,最后把这三部分能装水的最大值加起来,就是问题的答案。

      其中getPartWater()函数是用来计算两个木块之间能装水的最大值。其主要思想是先求最左和最右木块高度的最小值minHeight,然后用minHeight来填充在这两条木块之间的空隙,用总的面积减去在填充区域之间实际木块的面积,就是能装水的最大值


时间复杂度分析:

        时间复杂度似乎比较难分析?


以下是代码:

public class Solution {    private int getPartWater(int i , int j , int[] height){int barSum = 0;int minHeight = Math.min(height[i], height[j]);for(int k=i ; k<=j ; ++k){barSum += Math.min(height[k], minHeight);}int ans = (j-i+1)*minHeight - barSum;return Math.max(ans, 0);}private int getAns(int[] height , int left , int right){int ans = 0;int maxValue1 = -1 , maxValue2 = -1;int maxIndex1 = 0 , maxIndex2 = 0;for(int i=left ; i<=right ; ++i){if(height[i]>maxValue1){maxValue1 = height[i];maxIndex1 = i;}}for(int i=left ; i<=right ; ++i){if(height[i]>maxValue2 && i!=maxIndex1){maxValue2 = height[i];maxIndex2 = i;}}int leftIndex = Math.min(maxIndex1, maxIndex2);int rightIndex = Math.max(maxIndex1, maxIndex2);if(leftIndex < rightIndex){ans += getPartWater(leftIndex, rightIndex, height);}if(leftIndex > left){ans += getAns(height, left, leftIndex);}if(rightIndex < right){ans += getAns(height, rightIndex, right);}return ans;}public int trap(int[] height) {return getAns(height, 0, height.length-1);    }}

0 0
原创粉丝点击