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 ] <i : temp += 1

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

    def trap(self, height):
        # 解法1 : 按第i行进行遍历,看height[i]与i的大小比较
        #          若height[i] >= i: res += temp temp = 0
        #          若height[i] < i: temp += 1
        res = 0
        max_water_level = 0
        for i in range(len(height)):
            if height[i] > max_water_level:
                max_water_level = height[i]
        for i in range(1,max_water_level + 1):
            temp = 0
            isStart = False
            for j in range(len(height)):
                if height[j] < i and isStart:# 之前没有比i高的柱子就没有水
                    temp += 1
                if height[j] >= i:
                    res += temp
                    temp = 0
                    # 之前有比i高的柱子了
                    isStart = True
        return res

2.聚焦于求每列的水

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

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

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

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

python:

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

java:

public int trap(int[] height) {
    int res = 0, i,j;
    for(i = 1 ; i < height.length - 1 ; i++){
        int left_max = 0;
        int right_max = 0;
        for(j = 0 ; j <= i-1 ; j++){
            if(height[j] > left_max)
                left_max = height[j];
        }
        for(j = i+1 ; j < height.length ; j++){
            if(height[j] > right_max)
                right_max = height[j];
        }
        int lower_max = Math.min(left_max,right_max);
        if (lower_max > height[i]){
            res += (lower_max - height[i]);
        }
    }
    return res;
}

 

 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]小,则盛水量即为两值之差。

    def trap(self, height):
        res = 0
        lens = len(height)
        max_left,max_right = [0] * lens,[0] * lens
        for i in range(1,lens):
            max_left[i] = max(max_left[i-1],height[i-1])
        for i in range(lens-2,-1,-1):
            max_right[i] = max(max_right[i+1],height[i+1])
        for i in range(lens-1):
            lower_max = min(max_left[i],max_right[i])
            if lower_max > height[i]:
                res += (lower_max - height[i])
        return res

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

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

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

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

    def trap(self, height):
        # 解法5 : 栈
        # helper[]
        current_index,lens = 0,len(height)
        helper = []
        res = 0
        while current_index < lens:
            # 栈不为空且当前指向高度大于栈顶元素高度
            while helper and height[helper[-1]] < height[current_index]:
                x = height[helper[-1]]
                helper.pop()
                if not helper:
                    break
                # 计算当前存储的水量
                distance = current_index - helper[-1]- 1
                hit = min(height[current_index],height[helper[-1]])
                res += (distance * (hit -x ))
            helper.append(current_index)
            current_index += 1
        return res

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值