动态规划
- left_max[i] = height[i]左侧的最高高度
- right_max[i] = height[i]右侧的最高高度
- height[i]能接多少水?min(left_max[i], right_max[i])-height[i]
class Solution {
public:int trap(vector<int>& height) {int len = height.size();vector<int> left_max(len,0); vector<int> right_max(len,0); left_max[0] = height[0];for(int i=1;i<len;i++){left_max[i] = max(left_max[i-1],height[i]);}right_max[len-1] = height[len-1];for(int i=len-2;i>=0;i--){right_max[i] = max(right_max[i+1],height[i]);}int res = 0;for(int i=0;i<len;i++){res += (min(left_max[i], right_max[i]) - height[i]);}return res;}
};
- 优化:左侧最高高度可以只使用一个int变量,遍历获取接水量时动态更新
class Solution {
public:int trap(vector<int>& height) {int len = height.size();int left_max = 0;vector<int> right_max(len,0);right_max[len-1] = height[len-1];for(int i=len-2;i>=0;i--){right_max[i] = max(right_max[i+1],height[i]);}int res = 0;for(int i=0;i<len;i++){left_max = max(left_max, height[i]);res += (min(left_max, right_max[i]) - height[i]);}return res;}
};
双指针
- 动态规划优化后依然需要维护左侧或者右侧的最高值,空间开销为O(n)
- 使用左右指针动态维护左侧和右侧最高值
class Solution {
public:int trap(vector<int>& height) {int res = 0;int left = 0;int right = height.size()-1;int left_max = 0;int right_max = 0;while(left<=right){if(left_max<=right_max){left_max = max(left_max,height[left]);res = res + left_max - height[left++];}else{right_max = max(right_max,height[right]);res = res + right_max - height[right--];}}return res;}
};
栈
- 从左到右遍历数组,遍历到下标 i 时
- 如果栈内至少有两个元素,记栈顶元素为 top
- top 的下面一个元素是 left,则一定有 height[left]≥height[top]
- 如果 height[i]>height[top],则得到一个可以接雨水的区域
- 该区域的宽度是 i−left−1
- 高度是 min(height[left],height[i])−height[top]
- 根据宽度和高度即可计算得到该区域能接的雨水量
- 在对 top 计算能接的雨水量之后,left 变成新的 top,重复上述操作
- 直到栈变为空,或者栈顶下标对应的 height 中的元素大于或等于 height[i]
class Solution {
public:int trap(vector<int>& height) {stack<int> mystack;int res = 0;for(int i=0; i<height.size(); i++){while (!mystack.empty() && height[i] > height[mystack.top()]) {int top = mystack.top();mystack.pop();if(mystack.empty()) break; int left = mystack.top();int curr_width = i - left - 1;int curr_height = min(height[left], height[i]) - height[top];res += curr_height*curr_width;}mystack.push(i);}return res;}
};