【算法练习】 暴力/备忘录/双指针 lc42. 接雨水

前言

大家好,今天是@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:

【算法练习】 暴力/备忘录/双指针 lc42. 接雨水_第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

【算法练习】 暴力/备忘录/双指针 lc42. 接雨水_第2张图片

此时的l_maxleft指针左边的最高柱子,但是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

 

你可能感兴趣的:(算法练习,leetcode,算法,c++,双指针)