两个直方图之间的最大水量是多少?

时间:2017-02-10 03:09:57

标签: algorithm

我最近遇到了这个问题:

  

每个宽度为1的n直方图的高度。您必须选择任意两个直方图,如果它开始下雨并且所有其他直方图(除了您选择的两个直方图)被删除< / strong>,然后在两个直方图之间收集的水最大化。

Input: 9 3 2 5 9 7 8 1 4 6 Output: 25 在第三个和最后一个直方图之间。

这是Trapping rain water问题的变体。

我尝试了两种解决方案,但两者的最坏情况都是N ^ 2。我们如何进一步优化。

  • Sol1:每对的蛮力。

    int maxWaterCollected(vector<int> hist, int n) {
        int ans = 0;
        for (int i= 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                ans = max(ans, min(hist[i], hist[j]) * (j - i - 1));
            }
        }
    
        return ans;
    }
    
  • Sol2:按照高度递增顺序保留一系列直方图。对于每个直方图,在此序列中找到其最佳直方图。现在,如果所有直方图都按递增顺序排列,那么这个解决方案也会变成N ^ 2.

    int maxWaterCollected(vector<int> hist, int n) {
        vector< pair<int, int> > increasingSeq(1, make_pair(hist[0], 0)); // initialised with 1st element.
        int ans = 0;
        for (int i = 1; i < n; i++) {
            // compute best result from current increasing sequence
            for (int j = 0; j < increasingSeq.size(); j++) {
                ans = max(ans, min(hist[i], increasingSeq[j].first) * (i - increasingSeq[j].second - 1));
            }
    
            // add this histogram to sequence
            if (hist[i] > increasingSeq.back().first) {
                increasingSeq.push_back(make_pair(hist[i], i));
            }
        }
    
        return ans;
    }
    

2 个答案:

答案 0 :(得分:2)

使用2个迭代器,一个来自begin(),另一个来自end() - 1

  • 直到2迭代器相等:
  • 将当前结果与最大值进行比较,并保持最大值
  • 使用较小的值移动迭代器(开始 - >结束或结束 - >开始)

复杂性:O(n)

答案 1 :(得分:1)

Jarod42有正确的想法,但从他的简洁帖子中不清楚为什么他的算法(下面用Python描述)是正确的:

def candidates(hist):
    l = 0
    r = len(hist) - 1
    while l < r:
        yield (r - l - 1) * min(hist[l], hist[r])
        if hist[l] <= hist[r]:
            l += 1
        else:
            r -= 1


def maxwater(hist):
    return max(candidates(hist))

正确性的证明是通过归纳:最佳解决方案要么(1)属于到目前为止产生的候选者,要么(2)选择[l, r]内的直方图。基本情况很简单,因为所有直方图都在[0, len(hist) - 1]内。

归纳地,假设我们即将推进lr。这些案例是对称的,所以我们假设我们即将推进l。我们知道hist[l] <= hist[r],因此值为(r - l - 1) * hist[l]。给定任何其他正确的端点r1 < r,值为(r1 - l - 1) * min(hist[l], hist[r1]),因为r - l - 1 > r1 - l - 1hist[l] >= min(hist[l], hist[r1])较少。我们可以排除所有这些解决方案的次优,因此推进l是安全的。