接雨水
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
左右一高一低。
栈为单调递减 没有溢出
遇到增的时候 — pop 至栈为 单调递减—
溢出部分 = 木桶的最低值(一高一低) * (宽度) i当前位置-pop溢出位置 -1 之间的位置
木桶的最低值 = Math.max 当前位置 和溢出位置。
单调栈
public int trap(int[] height) {
//是
int ans = 0;
Deque<Integer> stack = new LinkedList<Integer>();
int n = height.length;
for (int i = 0; i < n; ++i) {
// 只有左右 高 中间低才能有 木桶
// height[i]>height[stack.peek()] ***右高** stack 为单调递减
while (!stack.isEmpty() && height[i] > height[stack.peek()]) {
// pop出 left值, 直到为左边界
int top = stack.pop();
if (stack.isEmpty()) {
break;
}
int left = stack.peek();
// 宽度 = 当前 - left -1; // left 和 cur 之间的距离增加
int currWidth = i - left - 1;
// 缺失高度 = 木桶的最小值(当前 和 栈上的高度)- pop的比较小的高度
// ****i>top*** left>top???? 显然, 不弹出 stack里面 是一个降序的
int currHeight = Math.min(height[left], height[i]) - height[top];
ans += currWidth * currHeight;
}
// 新增一个
stack.push(i);
}
return ans;
}
动态规划
每一个位置 缺失高度 = (–>left)左右(<–)到当前最大高度中 木桶最小值
public int trap(int[] height) {
// 动态规划
// 每一个柱子的缺失高度 = (leftMax,rightMax)木桶最小值 - 当前柱子高度
int n = height.length;
if (n == 0) {
return 0;
}
int[] leftMax = new int[n];
leftMax[0] = height[0];
for (int i = 1; i < n; ++i) {
leftMax[i] = Math.max(leftMax[i - 1], height[i]);
}
int[] rightMax = new int[n];
rightMax[n - 1] = height[n - 1];
for (int i = n - 2; i >= 0; --i) {
rightMax[i] = Math.max(rightMax[i + 1], height[i]);
}
int ans = 0;
for (int i = 0; i < n; ++i) {
ans += Math.min(leftMax[i], rightMax[i]) - height[i];
}
return ans;
}
双指针
左边界,右边界 leftMax从左(–>)的左边界,rightMax右边界
溢出值= Math.min(rightMax,leftMax) - 当前高度
h[left] < h[right] Math.min = leftMax 左指针++
h[left] > h[right] Math.min = rightMax 右指针–
溢出总高度
public int trap(int[] height) {
int ans = 0;
int left=0,right=height.length-1;
int leftMax =0,rightMax =0;
while (left<right){
// 当前值为最高值 - ans 为0. 达到最高峰的时候,没有溢出.
// 当前值不为最高值 ans 减去较小的木桶 ans+= (minMax- height[cur])
leftMax=Math.max(leftMax,height[left]);
rightMax=Math.max(rightMax,height[right]);
if (height[left]<height[right]){
// 木桶较小值 为左边. ans + 溢出部分 左边区域最值leftMax - 当前高度
ans += leftMax -height[left];
left++;
}else {
ans += rightMax -height[right];
right--;
}
}
return ans;
}