这个题刚开始看,一点思路也没有呀。。。。然后就迫不及待的看了题解。也不知道什么时候能积累出量变
这个题虽然标记为困难,但是其实不难。最简单的办法,我们计算每个位置的储水量:Min(maxL,maxR)-height[i]
我们在计算i位置上的储水量,分别向左向右找到最大值即可。 124ms
public static int trap(int[] height) {
int len = height.length;
if (len <= 2) return 0;
int ans = 0;
for (int i = 1; i < len - 1; i++) {
int maxLeft = 0;
int maxRight = 0;
for (int j = i - 1; j >= 0; j--) {
maxLeft = Math.max(maxLeft, height[j]);
}
for (int j = i + 1; j < len; j++) {
maxRight = Math.max(maxRight, height[j]);
}
int cur = Math.min(maxLeft, maxRight) - height[i];
ans += cur > 0 ? cur : 0;
}
return ans;
}
仔细思考一下,我们不停的向左、向右(向前看~~,不知不觉的唱了起来呢)寻找最大值,其实可以通过一次遍历,然后记录下来最大值
maxL[i]表示 i以左的最大值,maxR[i]表示i以右的最大值。
在稍微思考一下,maxL maxR应该是包含i本身的。于是 2ms
public static int trap2(int[] height) {
int len = height.length;
if (len <= 2) return 0;
int[] maxLeft = new int[len];
int[] maxRight = new int[len];
maxRight[len - 1] = height[len - 1];
maxLeft[0] = height[0];
for (int i = 1; i < len; i++)
maxLeft[i] = Math.max(maxLeft[i - 1], height[i]);
for (int i = len - 2; i >= 0; i--)
maxRight[i] = Math.max(maxRight[i + 1], height[i]);
int ans = 0;
for (int i = 1; i < len - 1; i++) {
int cur = Math.min(maxLeft[i], maxRight[i]) - height[i];
ans += cur;
}
return ans;
}
我们在深入思考一下,可以用栈来存储没有计算储水值的索引。 当 height[i]>height[stack.peek()]的时候,第i个位置就可以和栈中的下一个索引,形成一个容器,在索引statck.peek这里储水。直到栈被清空,所有能储水的位置就被计算完成了。
我们计算出所有位置,就可以得到结果。 4ms
public static int trap3(int[] height) {
int len = height.length;
if (len <= 2) return 0;
int ans = 0;
Stack<Integer> s = new Stack();
int cur = 0;
while (cur < len) {
while (!s.empty() && height[cur] > height[s.peek()]) {
int top = s.peek();
s.pop();
if (s.empty()) break;
int wid = cur - s.peek() - 1;
int hei = Math.min(height[cur], height[s.peek()]) - height[top];
ans += hei * wid;
}
s.push(cur++);
}
return ans;
}
来源:oschina
链接:https://my.oschina.net/u/4367530/blog/3220132