Leetcode42. 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.
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. Thanks Marcosfor contributing this image!
Example:
Input: [0,1,0,2,1,0,1,3,2,1,2,1] Output: 6
思路:
一个柱能不能储水是看它的左边的最大值和右边的最大值,我们可以首先从左向右遍历找出左边的最大值,然后再从右向左遍历找出右边最大值,同时判断该柱状是否可以储水,即将该柱的值与左右两边最大值的最小值相比较,如果大于最小值,说明无法储水,小于最小值,则可以储水。
代码:
class Solution { public: int trap(vector<int>& height) { if(height.size() < 2) return 0; int water = 0; int maxH = 0; vector<int> left; for(int i = 0; i < height.size(); i++){ left.push_back(maxH); maxH = max(maxH, height[i]); } maxH = height[height.size()-1]; for(int i = height.size() - 2; i > -1; i--){ int shorter = min(maxH, left[i]); maxH = max(maxH, height[i]); if(shorter <= height[i]) continue; water += (shorter - height[i]); } return water; } };
时间复杂度应该为O(n), 空间复杂度也为O(n),但是是经过了两轮遍历。
OJ后只在21%左右,所以一定存在更优的方案。
改进:
上面的方法我们遍历数组了两次,优化方法可以尝试只遍历数组一次。
代码:
class Solution { public: int trap(vector<int>& height) { if(height.size() < 3) return 0; int leftW = height[0]; int rightW = height[height.size() - 1]; int water = 0; int left = 1; int right = height.size() - 1; while(left <= right){ if(leftW <= rightW){ water += max(leftW - height[left], 0); leftW = max(height[left], leftW); left++; }else{ water += max(rightW - height[right], 0); rightW = max(height[right], rightW); right--; } } return water; } };