2023.8.29
本题可以用双指针做,求出每一列能盛的雨水,再相加即可。不过暴力法会超时,需要优化。
双指针(暴力):
class Solution {
public:
int trap(vector<int>& height) {
int ans = 0;
for(int i=1; i<height.size()-1; i++)
{
int max_rheight = height[i]; //记录当前柱子右边的最高柱子
int max_lheight = height[i]; //记录当前柱子左边的最高柱子
for(int r=i+1; r<height.size(); r++)
{
max_rheight = max(max_rheight,height[r]);
}
for(int l=i-1; l>=0; l--)
{
max_lheight = max(max_lheight,height[l]);
}
ans += max(0 , min(max_rheight,max_lheight)-height[i]);
}
return ans;
}
};
双指针(优化):
上面双指针暴力法每次遍历都需要求一次当前柱子左右两侧的最高柱子,这样有重复,自然会超时。 优化办法是设置两个数组left和right,分别存储每一个柱子的左侧最高柱子,及右侧最高柱子,这样子就不用重复遍历了。 代码如下:
class Solution {
public:
int trap(vector<int>& height) {
//求出当前柱子的左侧最高柱子以及右侧最高柱子,保存在两数组中。
vector<int> left(height.size());
vector<int> right(height.size());
int max_lheight = height[0];
int max_rheight = height[height.size()-1];
for(int i=1; i<left.size()-1; i++)
{
left[i] = max_lheight;
max_lheight = max(max_lheight,height[i]);
}
for(int i=right.size()-2; i>=1; i--)
{
right[i] = max_rheight;
max_rheight = max(max_rheight,height[i]);
}
//遍历每一列求出最大雨水
int ans = 0;
for(int i=1; i<height.size()-1; i++)
{
ans += max(0 , min(left[i],right[i])-height[i]);
}
return ans;
}
};
2023.10.1
二刷。 还是原来的思路,用left和right数组记录当前柱子左侧的最大柱子 和 当前柱子右侧的最大柱子,但是第一个柱子和最后一个柱子不需要记录,因为这两个柱子不能储水。
最近开始学java,用java撸的代码:
class Solution {
public int trap(int[] height) {
int left[] = new int [height.length];
int right[] = new int [height.length];
int left_max = height[0];
int right_max = height[height.length-1];
//不需要遍历到数组的首元素和尾元素
for(int i=1; i<height.length-1; i++){
left[i] = left_max;
left_max = Math.max(left_max,height[i]);
}
for(int i=height.length-2; i>=1; i--){
right[i] = right_max;
right_max = Math.max(right_max,height[i]);
}
//求面积和
int ans = 0;
for(int i=1; i<height.length-1; i++){
ans += Math.max(0 , Math.min(left[i],right[i])-height[i]);
}
return ans;
}
}
还是有点不习惯的,比如max要用Math.max,.size()变成了.length。数组的定义也有点区别,慢慢熟悉把。