没做出来,看的官解。
1. 动态规划的思想
当位于i处,i处能接水的体积=左侧最高点和右侧最高点的最小值(水桶原理)-自身的高度
java
class Solution {
public int trap(int[] height) {
int sum = 0;
int n = height.length;
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]);
}
for(int i=0;i<n;i++){
sum += Math.min(rightMax[i], leftMax[i]) - height[i];
}
return sum;
}
}
2. 采用单调栈计算
只要有凹槽就可以储水,首先将元素放入单调栈中,然后循环数组与栈顶对比。
此时:如果该元素(相当于右侧)大于栈顶的元素(相当于底部)再加上栈顶的下一个元素(相当于左侧,单调栈,栈顶元素一定小于第二个元素)就形成了凹槽。
java
class Solution {
public int trap(int[] height) {
int n = height.length;
int res = 0;
Deque<Integer> stack = new ArrayDeque<>();
for(int i = 0;i<n;i++){
int right = i;
while( !stack.isEmpty() && height[right] > height[stack.peek()]){
int bottom = stack.pop();
if(stack.isEmpty()){
// 左侧无元素,无法形成凹槽
break;
}
int left = stack.peek();
int w = right - left - 1;
int h = Math.min(height[right], height[left]) - height[bottom];
res += w*h;
}
stack.push(i);
}
return res;
}
}
3. 采用双指针
按照动态规划的思路,只需要维护leftMax,rightMax两个变量就可以将空间降至O(1)
java
class Solution {
public int trap(int[] height) {
int res = 0;
int left = 0,right = height.length - 1;
int leftMax = 0,rightMax = 0;
while(left < right){
leftMax = Math.max(leftMax, height[left]);
rightMax = Math.max(rightMax, height[right]);
if(leftMax < rightMax){
// 根据水桶原理,leftMax比rightMaxx小,此时,无论右边多大,水超过leftMax就会溢出。
res += leftMax - height[left++];
}else{
res += rightMax - height[right--];
}
}
return res;
}
}