代码随想录算法训练营第五十九天| LeetCode503. 下一个更大元素 II、LeetCode42. 接雨水

一、LeetCode503. 下一个更大元素 II

        1:题目描述(503. 下一个更大元素 II

        给定一个循环数组 nums ( nums[nums.length - 1] 的下一个元素是 nums[0] ),返回 nums 中每个元素的 下一个更大元素 。

        数字 x 的 下一个更大的元素 是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1 。

        2:解题思路

class Solution:
    def nextGreaterElements(self, nums: List[int]) -> List[int]:
        # # 用两个nums数组,拼成一个nums_pin,然后再使用单调栈
        # result = [-1] * (2*len(nums))
        # res_stack = [0]
        # nums_pin = nums[:]
        # for item in nums:
        #     nums_pin.append(item)
        # for i in range(1, len(nums_pin)):
        #     if nums_pin[i] <= nums_pin[res_stack[-1]]:
        #         res_stack.append(i)
        #     else:
        #         while len(res_stack)!=0 and nums_pin[i] > nums_pin[res_stack[-1]]:
        #             index = res_stack.pop()
        #             result[index] = nums_pin[i]
        #         res_stack.append(i)
        # return result[:len(nums)]

        # 循环遍历nums
        result = [-1]*len(nums)
        res_stack =[0]
        for i in range(1, 2*len(nums)):    # 遍历长度为两个nums
            # 当前遍历的值i,除以nums的长度取余,就可以得到当前i对应在nums中的下标
            if nums[i%len(nums)] <= nums[res_stack[-1]]:
                res_stack.append(i%len(nums))
            else:
                while len(res_stack)!=0 and nums[i%len(nums)] > nums[res_stack[-1]]:
                    index = res_stack.pop()
                    result[index] = nums[i%len(nums)]
                res_stack.append(i%len(nums))
        return result

二、LeetCode42. 接雨水

        1:题目描述(42. 接雨水

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

        2:解题思路

        解法一:双指针

class Solution:
    def trap(self, height: List[int]) -> int:
        # 按照列来计算雨水的高度,雨水的宽度均为1,求出每列雨水的体积,然后求和
        # 双指针
        # 遍历数组height,求每列柱子的左侧最高高度left_height,右侧最高高度right_height,
        # 取两侧高度最小值 减去 柱子本身的高度,就是水滴的高度,min(left_height, right_height)-height[i]
        height_sum = 0
        for i in range(len(height)):
            # 第一个柱子和最后一个柱子不接水
            if i == 0 or i == len(height)-1:
                continue
            # 记录右边柱子的最高高度
            right_height = height[i]
            # 记录左边柱子的最高高度
            left_height = height[i]
            # 从当前遍历的下一个位置,开始遍历剩下的height,求当前遍历位置右边的最高高度
            for r in range(i+1, len(height)):
                if height[r] > right_height:
                    right_height = height[r]
            # 从当前遍历的上一个位置,开始遍历前面的height,求当前遍历位置左边的最高高度
            for l in range(i-1, -1, -1):
                if height[l] > left_height:
                    left_height = height[l]
            # 求当前位置能接水的高度,左右高度的最小高度 减去 当前位置本身的高度,
            h = min(left_height, right_height) - height[i]
            if h > 0:
                height_sum += h
        return height_sum

        解法二:动态规划

class Solution:
    def trap(self, height: List[int]) -> int:
        # 动态规划
        if len(height) <= 2:
            return 0
        res = 0
        maxleft = [0]*len(height)       
        maxright = [0]*len(height)
        # 记录每个柱子左边柱子的最大高度
        maxleft[0] = height[0]
        for l in range(1, len(height)):
            # 在前一个柱子左边的最大高度,和当前柱子的高度中取最大值
            maxleft[l] = max(maxleft[l-1], height[l])
        # 记录每个柱子右边柱子的最大高度,从后往前遍历
        maxright[len(height)-1] = height[len(height)-1]
        for r in range(len(height)-2, -1, -1):
            # 在后一个柱子右边的最大高度,和当前柱子的高度中取最大值
            maxright[r] = max(maxright[r+1], height[r])
        # 求和
        for i in range(len(height)):
            h = min(maxleft[i], maxright[i]) - height[i]
            if h > 0:
                res += h
        return res

        解法三:单调栈

class Solution:
    def trap(self, height: List[int]) -> int:
        # 单调栈
        # 按照行的方向来计算雨水
        # 从栈顶到栈底的顺序,从小到大
        # 通过三个元素来接水:栈顶、栈顶的下一个元素,以及即将入栈的元素
        # 雨水的高度是:min(凹槽左边高度, 凹槽右边高度) - 凹槽底部高度
        # 即:min(栈顶下一个元素,即将入栈的元素) - 栈顶的元素
        # 雨水的宽度是:凹槽右边的下标-凹槽左边的下标-1(只求中间宽度)
        res = 0
        res_stack = [0]
        for i in range(1, len(height)):
            # 情况一:即将入栈的元素小于栈顶元素,直接入栈
            if height[i] < height[res_stack[-1]]:
                res_stack.append(i)
            # 情况二:即将入栈的元素小于栈顶元素,将栈顶元素弹出,入栈即将入栈的元素
            # 因为,当前柱子高度和栈顶一致时,左边的一个是不可能存在雨水的,所以保留右侧新柱子
            # 需要使用最右边的柱子来计算
            elif height[i] == height[res_stack[-1]]:
                res_stack.pop()
                res_stack.append(i)
            # 情况三:即将入栈的元素大于栈顶元素,出现凹槽了
            else:
                # 抛出所有较低的柱子
                while res_stack and height[i] > height[res_stack[-1]]:
                    # 栈顶就是中间的柱子,就是凹槽底部的高度
                    mid_height = height[res_stack[-1]]
                    # 弹出栈顶元素
                    res_stack.pop()
                    if res_stack:
                        right_height = height[i]
                        left_height = height[res_stack[-1]]
                        # 两侧的最小高度 - 凹槽底部的高度
                        h = min(right_height, left_height) - mid_height
                        # 两侧柱子的中间宽度:右侧柱子的下标 - 左侧柱子的下标 - 1
                        w = i - res_stack[-1] -1
                        # 求体积
                        res += h*w
                # 栈为空,将当前元素入栈
                res_stack.append(i)
        return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值