爨爨爨好

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

▶ 一个有趣的算法题。给定一个非负数数组,把数组中各元素看做是宽度为 1,高度为其值的砖块,求这些砖块最大能盛多少水。如给定数组 [0, 1, 0, 2, 1, 0, 1, 3, 2, 1, 2, 1],则水量为 6。参考原题答案 https://leetcode.com/problems/trapping-rain-water/solution/

  

● 代码,598ms 。暴力枚举,对于每个格子,搜索其左右两侧最高的高度,两高度中的较小者与该格子自身高度的差即为该格子盛水量。

 1 class Solution
 2 {
 3 public:
 4     int trap(vector<int>& height)
 5     {
 6         const int size = height.size();
 7         int ans, i, j, max_l, max_r; 
 8         for (ans = 0, i = 1; i < size - 1; i++)
 9         {
10             max_l = max_r = 0;
11             for (j = i; j >= 0; max_l = max(max_l, height[j--])); 
12             for (j = i; j < size; max_r = max(max_r, height[j++]));
13             ans += min(max_l, max_r) - height[i];
14         }
15         return ans;
16     }
17 };

● 代码,12 ms,动态规划。从原数组中得到一个单调不减序列和一个单调不增序列,两序列的交集即为装水量。

  

 1 class Solution
 2 {
 3 public:
 4     int trap(vector<int>& height)
 5     {
 6         if (height.size() == 0)
 7             return 0;
 8         const int size = height.size();
 9         vector<int> left_max(size), right_max(size);
10         int ans, i;
11         for (ans = 0, left_max[0] = height[0], i = 1; i < size; i++)
12             left_max[i] = max(height[i], left_max[i - 1]);
13         for (right_max[size - 1] = height[size - 1], i = size - 2; i >= 0; i--)
14             right_max[i] = max(height[i], right_max[i + 1]);
15         for (i = 1; i < size - 1; i++)
16             ans += min(left_max[i], right_max[i]) - height[i];
17         return ans;
18     }
19 };

● 代码,13 ms,神奇的双指针法。简单的说明:lp 从左向右扫描,并且不断记录目前为止最高坎的高度,当遇到高度降低时发生积水,向 ans 添加本格的积水量(本格积水量等于最高高度减去当前高度);rp 从右向左扫描,工作方式类似。注意每次搜索下一格之前要先对 candidatex[ lp ] 和 candidatex[ rp ] 做一个比较,只在较低者那边进行上述维护和加值操作,这是为了使最后 lp 和 rp 相遇时汇合于整个数组的最高高度处,此时以该最高高度为分水岭,其左右两边的积水都已经算完,可以返回答案。

 1 class Solution
 2 {
 3 public:
 4     int trap(vector<int>& height)
 5     {
 6         int lp, rp, ans, lpmax, rpmax;
 7         for (ans = lpmax = rpmax = lp = 0, rp = height.size() - 1; lp < rp;)
 8         {
 9             if (height[lp] < height[rp])
10             {
11                 height[lp] >= lpmax ? (lpmax = height[lp]) : (ans += lpmax - height[lp]);
12                 lp++;
13             }
14             else 
15             {
16                 height[rp] >= rpmax ? (rpmax = height[rp]) : (ans += rpmax - height[rp]);
17                 rp--;
18             }
19         }
20         return ans;
21     }
22 };

 

posted on 2018-01-21 00:20  爨爨爨好  阅读(210)  评论(0编辑  收藏  举报