题目

题目连接:https://leetcode.com/problems...
如果只是从数组的左边扫描到右边,不可能在这种单向扫描时知道:在当前扫描到的的地板上方能够装多少水。因为能装多少水依赖于当前地板的两边的地形,而单向扫描时无法知道当前地板右边的地形。因此我们需要从两边向中间扫描

从这一题中能学习到一些扫描数据下标移动的技巧。

题解

class Solution
{
  public:
    int trap(vector<int> &height)
    {
        if (height.size() <= 2)
        {
            return 0;
        }
        int l = 0, r = height.size() - 1, l_max = height[l], r_max = height[r], water = 0;
        while (l < r)
        {
            if (height[l] < height[r])
            {
                l++;
                if (height[l] > l_max)
                {
                    l_max = height[l];
                }
                water += l_max - height[l];
            }
            else
            {
                r--;
                if (height[r] > r_max)
                {
                    r_max = height[r];
                }
                water += r_max - height[r];
            }
        }
        return water;
    }
};

时间复杂度显然为O(n),一趟双向扫描就可以得到结果。

代码解释

我们维护2个扫描游标:lr
为了知道l的左边的地形,我们维护了一个变量l_max,表示l左边(包括l)最高的墙有多高。同理,r_max表示r右边(包括r)最高的墙有多高。
每次移动游标时,我们只移动lr中处于较低地形的游标。

不妨假设我们移动的是l

  • 如果l移动后的位置比l_max要低,那么l所在的地板上方必定能困住l_max-l的水量,因为l的左边有l_max比它高,右边有r比它高,且rl_max高(这一点比较难想到,请回想我们每次只移动比较低的游标)。此时将这些被困住的水量l_max-l记录到water结果变量中。
  • 如果l移动后的位置与l_max相同或更高,那么l所在的地板上方肯定不能困住水(因为l的左边没有更高的墙了)。并且更新l_maxl所在的高度。

示意图

最后两个游标肯定会在整个数组的最高点相遇!(请再次回想我们每次只移动比较低的游标)

总结

扫描数据和下标移动的技巧

可以看出,“每次只移动lr中处于较低地形的游标”是一个非常巧妙的选择,它为我们移动后的状态提供了一些保障。比如说l<r,因此移动l,我们可以确信,移动以后l的右边肯定有比l更高的墙(至少r就比l要高)。更进一步地,可以保证:此次保持不动的游标r肯定是当前已扫描到的地形的最高点(用反证法可以证明)。
l_max也有着更一般的含义:它象征着游标l已经扫描到的信息。r_max同理。扫描的过程中,我们可以存储那些有用的信息,以便将来与新的扫描结果相比较/做计算。

计算问题

不像这一题这一题,本题并不是一个搜索问题。本题要求我们根据给定的信息计算出某种结果,不妨称它为计算问题。
对于计算问题,算法的步骤一般是:

  1. 扫描输入数据,提取、存储有用信息。
  2. 根据扫描得到的信息来进行计算,得到结果。

以下几个因素会影响到扫描的次数和计算阶段的复杂度:

  • 每趟扫描获取到的信息数量
  • 信息的存储方式
  • 存储之前如何处理信息

因此,理想的计算问题算法应该:

  • 尽可能地在一趟扫描中收集更多信息
  • 存储信息的数据结构应该适应将来的计算算法
  • 在扫描的过程中就处理信息,减轻计算阶段的负担
搜索问题也需要扫描输入,上面的建议同样适用。

与积分之间的关联

这道题不禁让人联想到数学里的积分:
clipboard.png


csRyan
1.1k 声望198 粉丝

So you're passionate? How passionate? What actions does your passion lead you to do? If the heart doesn't find a perfect rhyme with the head, then your passion means nothing.