这个题刚开始看,一点思路也没有呀。。。。然后就迫不及待的看了题解。也不知道什么时候能积累出量变
这个题虽然标记为困难,但是其实不难。最简单的办法,我们计算每个位置的储水量: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; }