大家好,今天是@LetItbeSun 坚持每日两题的第19天。(
这个题目是学习labuladong的高频面试题,这个题目的形式不常见,所以我也没有什么思路,是看了题解之后理解的
参考链接:https://mp.weixin.qq.com/s?__biz=MzAxODQxMDM0Mw==&mid=2247484482&idx=1&sn=9503dae2ec50bc8aa2ba96af11ea3311&chksm=9bd7fa4aaca0735c37ab72b40f5594def9f4f8ad76df4450be0c8ae1cdc2e0105a3fce1bc502&scene=178&cur_album_id=1318896187793260544#rd
42. 接雨水
难度困难2139
给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
示例 1:
输入:height = [0,1,0,2,1,0,1,3,2,1,2,1] 输出:6 解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。
示例 2:
输入:height = [4,2,0,3,2,5] 输出:9
提示:
n == height.length
0 <= n <= 3 * 104
0 <= height[i] <= 105
总结来说就是短板思想,就是对于每一个height[i]考虑它左边最高的板子和右边最高的板子,而height[i]能装的雨水=min(leftmax,rightmax)-height[i]
思路确定,接下来就是实现方法。
我们发现解决这个问题的关键就是求每个height[i]的leftmax和rightmax
这个方法没什么说的就是对每个heght[i]都暴力枚举找到它的leftmax和rightmax 时间复杂度O(N^2)
对于方法一的改进,方法二就是用空间换时间,建立leftmax和rightmax分别在O(N)时间内计算出它们的值。
int trap(vector& height) {
//备忘录解法
int n=height.size();
//注意空集的时候返回
if(n==0){
return 0;
}
int ans=0;
vector lmax(n,0),rmax(n,0); //lmax[i]表示h{0..i]中最高的 rmax[i]表示h[i...n-1]中最高的
lmax[0]=height[0];
rmax[n-1]=height[n-1];
for(int i=1;i=1;i--){
rmax[i]=max(height[i],rmax[i+1]);
}
for(int i=1;i
从两头开始用双指针left、right,对于这两个指针指到的left、right
此时的
l_max
是left
指针左边的最高柱子,但是r_max
并不一定是left
指针右边最高的柱子,这真的可以得到正确答案吗?其实这个问题要这么思考,我们只在乎
min(l_max, r_max)
。对于上图的情况,我们已经知道l_max < r_max
了,至于这个r_max
是不是右边最大的,不重要,重要的是height[i]
能够装的水只和l_max
有关。
l_max < r_max的情况,我们等于知道了右边的板子有比lmax还大的,根据短板决定,所以height[i]能够装的水就和l_max有关,
而l_max也正好就是left指针左边最高的柱子,同理right指针也一样。
int trap(vector& height) {
//双指针法
int n=height.size();
if(n==0){
return 0;
}
int left=0,right=n-1;
int lmax=height[0],rmax=height[n-1];
int ans=0;
while (left<=right){
//更新lmax rmax
lmax=max(height[left],lmax);
rmax=max(height[right],rmax);
//左边的短板就累加left所在的height 右边的短板就累加right所在的height
if(lmax