Leetcode-面试题17.21 直方图的水量
作者:互联网
动态规划——用空间换时间
明确思路:对于下标 i,水能到达的最大高度等于下标 i 两边的最大高度的最小值,下标 i 处能接的水的量等于下标 i 处的水能到达的最大高度减去 height[i]
时间复杂度:O(n)
空间复杂度:O(n)
class Solution {
public:
int trap(vector<int>& height) {
int n=height.size();
if(n==0){
return 0;
}
//使用两个向量存储每个位置两边的最大高度
vector<int> leftmax(n),rightmax(n);
leftmax[0]=height[0];
//正向遍历获得leftmax的值
for(int i=1;i<n;i++){
leftmax[i]=leftmax[i-1];
if(height[i]>leftmax[i]){
leftmax[i]=height[i];
}
}
rightmax[n-1]=height[n-1];
//逆向遍历获得rightmax的值
for(int i=n-2;i>=0;i--){
rightmax[i]=rightmax[i+1];
if(height[i]>rightmax[i]){
rightmax[i]=height[i];
}
}
int ans=0;
//计算每个位置的储水量
for(int i=0;i<n;i++){
ans+=min(leftmax[i],rightmax[i])-height[i];
}
return ans;
}
};
单调栈
让栈保持递减存储,可以肯定栈底一定是栈中的最大值,stack[0]永远是最大值
每次向后读一个数据,若比栈顶元素小直接压栈,反之准备盛水
栈中所有小于当前数据的元素,都要与当前数据增长到同等高度,弹栈,增长的高度用水填满
时间复杂度:O(n)
空间复杂度:O(n)
class Solution {
public:
int trap(vector<int>& height) {
int ans=0;
int n=height.size();
stack<int> stk;
for(int i=0;i<n;i++){
//对栈中元素挨个比较,直到遇到比当前元素大的栈中元素
while(!stk.empty()&&height[i]>height[stk.top()]){
int top=stk.top();//栈顶元素top下面一个必是left,且高度一定低于left,若新节点高度高于top,必可得到一个接水区域
stk.pop();//弹栈
if(stk.empty()){
break;
}
int left=stk.top();
int currwidth=i-left-1;//注意下计算细节
int currheight=min(height[left], height[i])-height[top];//当前节点和左边节点的高度最小值-中间弹栈节点高度
ans += currwidth * currheight;
}
stk.push(i);
}
return ans;
}
};
双指针
class Solution {
public:
int trap(vector<int>& height) {
int ans = 0;
int left = 0, right = height.size() - 1;
//记录左右最高点
int leftMax = 0, rightMax = 0;
while (left < right) {
//移动后更新左右最高点
leftMax=max(leftMax,height[left]);
rightMax=max(rightMax,height[right]);
//当前位置谁高度小谁移动
if(height[left]>height[right]){
//右边最高点减去当前指针所在高度,即是当前指针位置储水量
ans+=rightMax-height[right];
right--;
}else{
//同上
ans+=leftMax-height[left];
left++;
}
}
return ans;
}
};
标签:leftmax,面试题,rightmax,17.21,height,int,直方图,ans,left 来源: https://blog.csdn.net/qq_43699254/article/details/115412586