zoukankan      html  css  js  c++  java
  • leetcode刷题笔记四十二 接雨水

    leetcode刷题笔记四十二 接雨水

    源地址:42. 接雨水

    问题描述:

    给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

    上面是由数组 [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

    代码补充:

    //方法一: 直接统计每个柱子的储水情况
    //对于单个柱子的储水值,受其左侧柱子最大高度及右侧柱子最大高度
    //即 储水值 = (左侧最大柱子高度与右侧最大柱子高度的较小值)- 当前柱子高度
    //实际处理过程中,需要将当前柱子加入到左右侧柱子最大高度的计算中,防止出现负数值,这种情况下整个数组的最大高度的储水值会为0
    //时间复杂度O(n^2) 空间复杂度O(1)
    
    import scala.math
    object Solution {
        def trap(height: Array[Int]): Int = {
            var res = 0
    		
            //就整个数组中的每个柱子的储水值进行计算
            for (i <- 0 until height.length){
    
                //将当前柱子高度包含在内,计算左侧柱子最大高度
                var max_left = 0
                for(j <- 0 to i){
                    if (height(j) > max_left) max_left = height(j)
                }
    
    			//将当前柱子高度包含在内,计算右侧柱子最大高度
                var max_right = 0
                for(j <- i until height.length){
                    if (height(j) > max_right) max_right = height(j)
                }
    
                //将每个柱子上的储水值进行统计
                res += (math.min(max_left, max_right) - height(i))    
            }
            return res
        }
    }
    
    
    //方法二: 动态规划
    //基于上述方法,可见对于每个柱子使用的数据主要为其max_left及max_right
    //构建两个数组 记录每个柱子的max_left和max_rigth
    //时间复杂度O(n) 空间复杂度O(n)
    import scala.math
    object Solution {
        def trap(height: Array[Int]): Int = {
            if (height.length == 0) return 0 
            var res = 0
            val max_left_matrix = new Array[Int](height.length)
            val max_right_matrix = new Array[Int](height.length)
            //初始化数组
            max_left_matrix(0) = height(0)
            max_right_matrix(height.length-1) = height(height.length-1)
    		
            //更新左侧柱子最大高度数组
            for(i <- 1 to height.length-1) max_left_matrix(i) = math.max(max_left_matrix(i-1),height(i))
    
    		//更新右侧柱子最大高度数组
            //注意Scala倒叙计数的方法, 使用reverse方法
            for(i <- (0 to height.length-2).reverse) max_right_matrix(i) = math.max(max_right_matrix(i+1), height(i))
    
            //根据公式,计算每个柱子的储水值并累加
            for(i <- 0 to height.length-1) res += math.min(max_left_matrix(i), max_right_matrix(i)) - height(i)
    
            return res
        }
    }
    
    //方法三:双指针法
    //维持一个稳定的max_left 和 max_right,将随着left,right指针收敛进行更新
    //时间复杂度O(n) 空间复杂度O(1)
    import scala.math
    object Solution {
        def trap(height: Array[Int]): Int = {
            if (height.length == 0) return 0 
    
            var res = 0
            var max_left = 0
            var max_right = 0
            var left = 0
            var right = height.length-1
    
            
            while(left <= right){
                //max_left <= max_right时,使用max_left进行判断
                //推动left向前,因为max_left较max_right小,若left
                //不向前,始终会选择max_eft作为评价
                if(max_left <= max_right){
                    max_left = math.max(max_left, height(left))
                    res += max_left - height(left)
                    left += 1
                }
                //同left直至双指针重合
                else{
                    max_right = math.max(max_right, height(right))
                    res += max_right - height(right)
                    right -= 1
                }
            }
    
            return res
        }
    }
    
    //方法四:单调栈
    //储水的槽构成需要三根柱子,即单调栈中比栈顶元素大的左侧柱
    //栈顶元素 与 目前访问的数组的柱高 这才可能构成凹槽储水
    //以图例演示储水情况
    // 4
    // 4 3 
    // 4 3 2
    // 4 3 2 0  ===》 因为缺乏有效的右侧,无法计算储水
    // 4 3 2 0  <--- 1 此处构成凹槽  将0弹出 计算高度为0的层的储水值 res += (4-2-1)*(1-0) 
    // 4 3 2 1 <---3 此处又构成凹槽  将1弹出 计算高度为1的层的储水值 res += (5-2-1)*(2-1)
    //以此类推
    import scala.math
    import scala.collection.mutable.Stack
    object Solution {
        def trap(height: Array[Int]): Int = {
            if (height.length == 0) return 0 
            
            var res = 0
            val stack = new Stack[Int]()
            
            for(i <- 0 to height.length-1){
                var last = 0
                while(stack.isEmpty == false && height(stack.top) <= height(i)){
                    val temp = stack.top
                    stack.pop
                    res += (i - temp - 1)*(height(temp) - last)
                    last =   height(temp)
                }
                if (stack.isEmpty == false) res += (i - stack.top - 1)*(height(i) - last)
                stack.push(i)
            }
    
            return res
        }
    }
    
  • 相关阅读:
    settTimeout vs setInterval
    JS继承
    JS创建对象
    原型链
    开始学习python的感受
    Problem 29
    Python 查看关键字
    Problem 21
    Problem 34
    Problem 42
  • 原文地址:https://www.cnblogs.com/ganshuoos/p/13203865.html
Copyright © 2011-2022 走看看