• LeetCode刷题(python版)——Topic42接雨水


    一、题设

    给定 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
    

    二、基本思路与代码实现

    1.按层暴力求解

            按第i行进行遍历,比较height[ i ]与i的大小:

                    1.若height [ i ] >= i : res += temp,temp = 0

                    2.若height [ i ]

            很可惜,这样做可恶的超出了时间限制。

    1. def trap(self, height):
    2. # 解法1 : 按第i行进行遍历,看height[i]与i的大小比较
    3. # 若height[i] >= i: res += temp temp = 0
    4. # 若height[i] < i: temp += 1
    5. res = 0
    6. max_water_level = 0
    7. for i in range(len(height)):
    8. if height[i] > max_water_level:
    9. max_water_level = height[i]
    10. for i in range(1,max_water_level + 1):
    11. temp = 0
    12. isStart = False
    13. for j in range(len(height)):
    14. if height[j] < i and isStart:# 之前没有比i高的柱子就没有水
    15. temp += 1
    16. if height[j] >= i:
    17. res += temp
    18. temp = 0
    19. # 之前有比i高的柱子了
    20. isStart = True
    21. return res

    2.聚焦于求每列的水

            1. 首先求[0 , i-1]中最高的柱子。

            2. 其次求[0 , i - 1]和[i + 1 , len - 1]中最高的柱子。

            3. 比较当前列高度和左右最高柱子的较低值,若当前列高度大,则没水;若当前列高度小,则水量为 左右最高柱子的较低值 - 当前柱子高度。

            这种做法产生了比较有意思的现象:java可以AC,而python差两个用例AC,在处理高并发、多数据量的情况下,java还是有得天独厚的优势!

    python:

    1. def trap(self, height):
    2. # 解法2 : 聚焦于求每列的水
    3. # 如何求某列的水:1.求[0,i-1]中最高的柱子 2.求[i+1,len-1]中最高的柱子 3.比较当前列高度和左右高柱子的较低值
    4. def max_height(nums,start,end):
    5. max_val = 0
    6. for index in range(start,end+1):
    7. if nums[index] > max_val:
    8. max_val = nums[index]
    9. return max_val
    10. res = 0
    11. lens = len(height)
    12. for i in range(1,lens-1):
    13. left_max = max_height(height,0,i-1)
    14. right_max = max_height(height,i+1,lens - 1)
    15. lower_max = min(left_max,right_max)
    16. if lower_max > height[i] :
    17. res += (lower_max - height[i])
    18. return res

    java:

    1. public int trap(int[] height) {
    2. int res = 0, i,j;
    3. for(i = 1 ; i < height.length - 1 ; i++){
    4. int left_max = 0;
    5. int right_max = 0;
    6. for(j = 0 ; j <= i-1 ; j++){
    7. if(height[j] > left_max)
    8. left_max = height[j];
    9. }
    10. for(j = i+1 ; j < height.length ; j++){
    11. if(height[j] > right_max)
    12. right_max = height[j];
    13. }
    14. int lower_max = Math.min(left_max,right_max);
    15. if (lower_max > height[i]){
    16. res += (lower_max - height[i]);
    17. }
    18. }
    19. return res;
    20. }

     

     3.动态规划

            另外定义数组:max_left[n]、max_right[n]

            1.max_left[i] 代表前[0,i-1]中的最大值,比较max_left[i-1]与height[i-1]即可

            2.max_right[i]代表后[i+1,n]中的最大值,比较max_right[i+1]与height[i+1]即可

            3.最后在[1,lens-1]中判断height[i]与max_left[i]和max_right[i]的小值哪个大,若height[i]大,则height没有水;若height[i]小,则盛水量即为两值之差。

    1. def trap(self, height):
    2. res = 0
    3. lens = len(height)
    4. max_left,max_right = [0] * lens,[0] * lens
    5. for i in range(1,lens):
    6. max_left[i] = max(max_left[i-1],height[i-1])
    7. for i in range(lens-2,-1,-1):
    8. max_right[i] = max(max_right[i+1],height[i+1])
    9. for i in range(lens-1):
    10. lower_max = min(max_left[i],max_right[i])
    11. if lower_max > height[i]:
    12. res += (lower_max - height[i])
    13. return res

     4.栈(参考括号匹配的问题)

            1.当栈为空或者栈顶元素>=当前下标元素时,height数组值在呈现下降的趋势,即当前位于坑的左边,所以这时还不知道这个水坑的深度有多少,所以继续往栈内存。

            2.当栈不为空或者栈顶元素<当前下标元素时,height数组值在呈现上升的趋势,即当前位于坑的右边,此时水坑的深度已经知道了,所以可以开始计算水量,每上一个台阶的时候,计算当前的水量即可。

            3.水量的计算:首先计算当前水量的长度distance,即当前下标值 - 栈顶存放的下标 - 1;其次计算高度height,即栈顶下标对应的值和当前下标对应值的较小值;最后计算水量的面积的时候要减掉上次计算过水量的高度值,即 s = distance * (height - h),其中 h 在每次计算前都等于前一个出栈的下标对应的值。

    1. def trap(self, height):
    2. # 解法5 : 栈
    3. # helper[]
    4. current_index,lens = 0,len(height)
    5. helper = []
    6. res = 0
    7. while current_index < lens:
    8. # 栈不为空且当前指向高度大于栈顶元素高度
    9. while helper and height[helper[-1]] < height[current_index]:
    10. x = height[helper[-1]]
    11. helper.pop()
    12. if not helper:
    13. break
    14. # 计算当前存储的水量
    15. distance = current_index - helper[-1]- 1
    16. hit = min(height[current_index],height[helper[-1]])
    17. res += (distance * (hit -x ))
    18. helper.append(current_index)
    19. current_index += 1
    20. return res

     

  • 相关阅读:
    Mybatis-plus修改指定字段
    UE基础必学系列:UMG
    第十五章总结
    优化 C++ 字符串拼接:高效方法与代码示例
    STM32 Cubemx 通用定时器 General-Purpose Timers同步
    【资损】资损防控的系统规范-收单类服务设计
    Simulink Test自动化(三)-创建TestReport和CoverageReport
    深度学习【使用pytorch实现基础模型、优化算法介绍、数据集的加载】
    Linux:进程(一)
    中文翻译英文-免费批量中文英文翻译互转软件
  • 原文地址:https://blog.csdn.net/weixin_54039182/article/details/127433592