阅读 70

LeetCode:Trapping Rain Water

题目描述

题目源自于

给定n个非负整数,代表着一个高度柱状图连续n个图的高度。本题需要计算这个柱状图能够蓄水的数量。

样例图

解题思路

蓄水的情况主要如下图:

假设heights代表所有的柱状图高度, heights[i](0<=i代表第i个柱状图的高度:

根据上图一、图二和图三可知:

  1. 当任意heights数值呈单调的时候,不存在蓄水量。
  2. heights仅存在类正态曲线的分布时,不存在蓄水量。

笔者先将情况缩小为len(heights) == 3,结合图四可知:

  1. heights[i] < heights[i+1] and heights[i] < heights[i-1]时存在蓄水量。
  2. 当前可以蓄水,蓄水量为(min(heights[i], heights[i-1]) - heights[i])
  3. 此时相当于heights[i] = min(heights[i], heights[i-1])

接下将场景扩大下len(heights) > 3,可参见图五和图六:

假设当前的bar的下标为k,检查蓄水的bar下标为i(i,此时任意j(i都有heights[i] < heights[j] < heights[j+1] < heights[k]

  1. heights[i-1] > heights[i]时存在蓄水量,执行2,否则执行5。
  2. 蓄水量相当于(min(min(heights[i+1:k+1]), heights[i-1]) - heights[i]) * (k-i)
  3. 此时相当于heights[i] = min(min(heights[i+1:k+1]), heights[i-1])
  4. i=i-1,执行步骤1。
  5. k=k+1,i=k-1执行步骤1。

根据上述步骤可以一步步获得最终的结果,得算法如下:

class Solution:
    def trap(self, height: List[int]) -> int:
        water = 0
        hi = 2
        while hi < len(height):
            if height[hi] < height[hi-1]:
                hi+=1
                continue
            bar = self._get_last_bar(height, hi-1, height[hi])
            while bar is not None:
                for i in range(hi-1, bar-1, -1):
                    water += min(height[hi], height[bar-1]) - height[i]
                    height[i] = min(height[hi], height[bar-1])
                bar = self._get_last_bar(height, bar-1, height[hi])
            hi+=1
        
        return water
    
    def _get_last_bar(self, height, lo, mh):
        if lo - 1 < 0:
            return None
        while lo - 1 >= 0 :
            if height[lo] < min(height[lo-1], mh):
                return lo
            lo-=1
        return None

上述算法实际上是O(n^2),算法还存在比较多得优化空间:

  1. 如使用栈来减少回朔(O(n)):
  2. 使用双指针遍历法(O(n)):

相关题目:

原文:https://www.cnblogs.com/kulor/p/14979616.html

文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐