我最近遇到了这个问题:
每个宽度为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;
}
答案 0 :(得分:2)
使用2个迭代器,一个来自begin()
,另一个来自end() - 1
。
复杂性: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]
内。
归纳地,假设我们即将推进l
或r
。这些案例是对称的,所以我们假设我们即将推进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 - 1
和hist[l] >= min(hist[l], hist[r1])
较少。我们可以排除所有这些解决方案的次优,因此推进l
是安全的。