[leetcode] Trapping Rain Water

思路1:

        使用递归的方法,直接考虑该问题,对于任意的这样一组数据,如果要求能容的最多的水,有一点是确定的:如果我们能找到数组里面的最大的两个数,那个这两个数之间能容的最多的水是确定的。设数据为An,而最大的两个数依次为ai,aj, 且i>j, 则trap(An) = trap(A[0:i]) + trap(A[i,j]) + trap(A[j,n]), 此算法的时间复杂度为nlgn, accepted的代码如下:

 1 class Solution {
 2 public:
 3     int cal_trap(vector<int>&height, int left, int right) {
 4         int result = 0;
 5         int max_height = std::min(height[left], height[right]);
 6         for(int i=left+1; i<right; i++) {
 7             result += (max_height-height[i]);
 8         }
 9         return result;
10     }
11     int cur_trap(vector<int>& height, int left, int right){
12         if (right-left <= 1) return 0;
13         int max_h = left, next_h = left;
14         int max_h_value = -1, next_h_value = -1;
15         for(int i=left; i<=right;i++) {
16             if(height[i] > max_h_value) {
17                 next_h_value = max_h_value;
18                 next_h = max_h;
19                 max_h = i;
20                 max_h_value = height[i];
21             } else if(height[i] > next_h_value){
22                 next_h = i;
23                 next_h_value = height[i];
24             }
25         }
26         int new_left = 0, new_right = 0;
27         if (max_h > next_h) {
28             new_left = next_h;
29             new_right = max_h;
30         } else {
31             new_left = max_h;
32             new_right = next_h;
33         }
34         return cal_trap(height, new_left, new_right) + cur_trap(height, left, new_left)
35             + cur_trap(height, new_right, right);
36     }
37     int trap(vector<int>& height) {
38         return cur_trap(height, 0, height.size()-1);
39     }
40 };

 

思路2:

  即是网上看到的时间复杂度为n的方法,利用stack结构,其原理是利用stack中只保存逐步递减的高度,然后,遇到比stack.top()的原理,则对结果进行加(相当于加水到某一高度),直接上代码:

 1 class Solution {
 2 public:
 3     
 4     int trap(vector<int>& height) {
 5         size_t s = height.size();
 6         if (s<3) return 0;
 7         int result = 0, bottom = 0;
 8         stack<int> slop;
 9         for (size_t i=0;i<height.size();i++) {
10             while(!slop.empty() && height[i] >=height[slop.top()]) {
11                 bottom = height[slop.top()];
12                 int cal_loc = slop.top();
13                 slop.pop();
14                 if(!slop.empty()) {
15                     result += (i-slop.top()-1) * (min(height[i], height[slop.top()])-bottom);
16                 }
17             }
18             slop.push(i);
19         }
20         return result;
21     } 
22 };

思路3:

  原理是对于某一位置,其上能容的最大的水是由其左边及右边的最高值确定的,即如果对ai, 其左边最高的值为al, 其右边最高的值为ar, 则在位置i, 其最多能容纳min(al, ar)-ai, 代码如下:

  

 1 class Solution {
 2 public:
 3     
 4     int trap(vector<int>& height) {
 5         size_t s = height.size();
 6         if(s<3) return 0;
 7         vector<int> left_max(s, 0);
 8         vector<int> right_max(s, 0);
 9         int max_left_value=0, max_right_value = 0;
10         for(size_t i=0;i<s;i++) {
11             if (height[i]>max_left_value) {
12                 max_left_value = height[i];
13             }
14             if (height[s-1-i] > max_right_value) {
15                 max_right_value = height[s-1-i];
16             }
17             left_max[i] = max_left_value;
18             right_max[s-1-i] = max_right_value;
19         }
20         int result = 0;
21         for (size_t i= 0;i<s;i++) {
22             result += std::min(left_max[i], right_max[i]) - height[i];
23         }
24         return result;
25     }  
26 };

 

posted @ 2018-06-03 23:36  力兜儿  阅读(154)  评论(0)    收藏  举报