力扣上承水问题有11和42题
一、承最多水的容器
解决思路:
要得到存储最大水量,得到max(长度 * 高度),使用双指针解决这类问题
先判断左指针还是右指针谁大,找最大值,保留最大值,让最小值向中间移动,即可保证高度会相对较高。
设置left左指针和right右指针,设置最大值max,当长度 * 高度大于max时替换,直到遍历完整个数组即可找到最大值max
class Solution {
public int maxArea(int[] height) {
int left = 0, right = height.length - 1, max = 0;
while(left < right ) {
//right - left计算长度,height[left++]计算长度,因为左边高度低于右边,让左指针右移一个,如果右边高度低于等于左边,让右指针左移一个。
max = height[left] < height[right] ?
Math.max(max, (right - left) * height[left++]) :
Math.max(max, (right - left) * height[right --]);
}
return max;
}
}
明白解决思路这题会比较简单。
二、接雨水
解决思路:
这题和上面题目类似,都是先找到左右两边最大的高度,找到矮的的那个,需要往中间移动
对比上面问题多两个个需要存储的参数,左边最高值(后面称为左高)和右边最高值(同理)
以左边为例,左高设置为0,判断左指针这个位置的高度是否高于左高,高于将左高值替换成当前左指针的高度,若当前值低于左高,左高-当前高度即为此格收集到的雨水数量,直到左指针大于右指针时结束。右边同理
class Solution {
public int trap(int[] height) {
//sum代表接雨水的总数
//left_max代表左高
//right_max则表示右高
//left、right代表对应位置
int sum = 0;
int left_max = 0;
int right_max = 0;
int left = 1;
int right = height.length - 2;
while(left <= right){
//此判断相当找最大的两边的墙
if(height[left - 1] < height[right + 1]){
//将左高和left当前高度比较找到最大的
left_max = Math.max(left_max, height[left - 1]);
//如果左高大于left当前高度,则证明left这一格接到了雨水
if(left_max > height[left]){
sum += (left_max - height[left]);
}
left++;
}else{
//右边同理
right_max = Math.max(right_max, height[right + 1]);
if (right_max > height[right]) {
sum = sum + (right_max - height[right]);
}
right--;
}
}
return sum;
}
}
总结:
接雨水问题解决办法使用双指针可以满足时间复杂度O(n),空间复杂度O(1),且思路容易,后续遇到类似问题以双指针解决即可