面试题 盛水 twitter

题目来源:http://news.cnblogs.com/n/192014/

 

用a[i]表示第i个墙的高度,墙的个数记为n

思考:

1)两个墙x,y之间可以盛水的条件是a[x],a[y]是a[x...y]中的前两大数;

2)如果a[1...x-1]中存在a[i]>a[x],那么用k来替代x并不会使a[x...y]中盛水减少,同样如果a[y+1...n]中存在a[j]>a[y],可以用j替代y不会使a[x...y]中的盛水减少;

3) 如果得到了a[1...n]中的前两大i,j,那么它们一定是整个区间盛水的最优边界,a[i...j]中的水位就是min{a[i],a[j]},只需要考虑两边:a[1...i]和a[j...n];对于左边,如果a[1...i-1]中最大值为a[k],那么进一步a[k...i]区间的盛水情况也确定了,只需要考虑a[1...k]了,右边也是如此。

4)设a[t]是a[1...n]中最大值,那么a[1...t]中的盛水情况可以通过维护左连续区间最大值确定,同样右区间a[t...n]也可以确定:首先找到最大值,然后分别从左右两边遍历。

5)一次遍历的做法很巧妙:维护两端区间的最大值,这样可以确定一端的水位了。

 

int cal(void)
{
    int ret = 0;
    int lmax = -1, rmax = -1;
    for (int i = 0, j = n-1; i <= j; ) {
        if (lmax < rmax) {
            if (a[i] > lmax) lmax = a[i];
            else ret += lmax-a[i];
            ++i;
        } else {
            if (a[j] > rmax) rmax = a[j];
            else ret += rmax-a[j];
            --j;
        }
     }
     return ret;
}

 

 

 

posted @ 2013-11-01 21:52  努力变瘦  阅读(159)  评论(0编辑  收藏  举报