一: 接雨水(双指针)
首先今天的每日一题是这个题的三D版本,所以先解决2D版本。
此题思路较为麻烦,采用的是左右双指针。针对一个地方可以存多少水,需要看他两边有没有比他高的柱子,而存多少水,则需要看两边比他高的柱子们的较小的高度。
我们维护 left 和 right 两个指针,还有对应的leftmax和rightmax两个对应的值。left 和 right 用来标记位置,两个max值用来标记左右两边此时遍历到的最大的值。
一开始,初始化left为0,right为数组长度减一。leftmax为左边第一个高度,rightmax为最后一个高度。开始遍历整个数组,看哪里有能存水的;接下来,因为能存多少水又较矮的决定,所以我们始终维护leftmax较小的情况(当然也可以是rightmax较小的情况)。leftmax较小说明能存多少水由leftmax决定,具体存的水是 : leftmax-height[left] (因为此时我们是有leftmax小于rightmax的假设的)。然后开始看下右移到一个位置可不可以存水,可以存多少水。右移到了下一个位置,left,leftmax都会更新,同时我们还要看leftmax<rightmax的条件是否被保持,若保持,此left位置同样用leftmax-height[left]求出存多少水。若不保持,则右边的成了小的,同理,right位置存的水量是rightmax-height[right]。接下来开始将left左移看leftmax与rightmax的大小情况,再接着判断下一步是右移或者左移,循环直到left==right。
class Solution {
public int trap(int[] height) {
int result=0;
int left=0;
int right=height.length-1;
int leftmax=height[left];
int rightmax=height[right];
while(left<right){
if(leftmax<rightmax){//右移
result+=leftmax-height[left];
left++;
leftmax=Math.max(leftmax,height[left]);
}
else{//左移
result+=rightmax-height[right];
right--;
rightmax=Math.max(rightmax,height[right]);
}
}
return result;
}
}
//时间复杂度O(n).
二.接雨水 Ⅱ (广度优先遍历)
1.此题目可抽象为广度优先遍历。
2.对于一个点:首先判断他是否能存水,方法是看周围有没有比他高的。
至于能存多少水,取决于这个点周围最矮的那个。
以后刷到深度优先遍历的题是再来补上。