代码随想录算法训练营Day 59 || 503.下一个更大元素II、42. 接雨水

503.下一个更大元素II

力扣题目链接(opens new window)

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

示例 1:

  • 输入: [1,2,1]
  • 输出: [2,-1,2]
  • 解释: 第一个 1 的下一个更大的数是 2;数字 2 找不到下一个更大的数;第二个 1 的下一个最大的数需要循环搜索,结果也是 2。

提示:

  • 1 <= nums.length <= 10^4
  • -10^9 <= nums[i] <= 10^9

  1. 初始化:创建一个栈来保存索引,一个数组 result 来存储结果,初始时该数组的所有值设为 -1(表示没有找到下一个更大的元素)。

  2. 双重遍历:由于这是一个循环数组,我们需要遍历两次数组。第一次遍历找到每个元素右侧的第一个更大的元素,第二次遍历用来找到那些在数组末尾但它们的更大元素在数组开头的情况。

  3. 栈的使用:在遍历的过程中,每次我们考察一个新元素时,我们检查栈顶元素代表的数组值是否小于当前元素。如果是,则我们找到了栈顶元素的下一个更大元素。我们在 result 数组的相应位置记录这个更大元素,然后将栈顶元素弹出。这个过程一直持续到栈为空或者栈顶元素代表的数组值大于等于当前元素。之后,将当前元素的索引压入栈中。

  4. 循环:由于数组是循环的,我们可以通过取模操作来模拟数组的循环。

class Solution:
    def nextGreaterElements(self, nums: List[int]) -> List[int]:
        n = len(nums)
        result = [-1] * n
        stack = []

        for i in range(2 * n):
            while stack and nums[stack[-1]] < nums[i % n]:
                result[stack.pop()] = nums[i % n]
            if i < n:
                stack.append(i)

        return result

42. 接雨水

力扣题目链接(opens new window)

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

在接雨水问题中,双指针法的核心思想是同时从数组的两端开始遍历,使用两个指针(leftright),分别代表数组的左端和右端。在这个过程中,我们维护两个变量(left_maxright_max),它们分别表示遍历到目前为止左侧和右侧遇到的最大高度。这样,我们可以在每个步骤中确定当前位置能够接收的雨水量。

  1. 初始化指针和变量:

    • left = 0(数组的开始位置)
    • right = len(height) - 1(数组的结束位置)
    • left_max = height[0]
    • right_max = height[len(height) - 1]
  2. 遍历数组:

    • 使用两个指针从两端开始遍历数组,直到它们相遇。
    • 在每个位置,更新 left_maxright_max
  3. 比较 left_maxright_max

    • 如果 left_max < right_max,则说明左边的柱子是短板,处理左边的柱子。
    • 否则,处理右边的柱子。
  4. 计算雨水量并累加:

    • 对于左边的柱子:left_max 是左边最高的柱子,height[left] 是当前柱子的高度,因此在位置 left 上的雨水量是 left_max - height[left]
    • 对于右边的柱子:同理,使用 right_max - height[right] 来计算雨水量。
    • 将计算出的雨水量累加到总量中。
  5. 移动指针:

    • 如果处理的是左边的柱子,将 left 指针向右移动(left += 1)。
    • 如果处理的是右边的柱子,将 right 指针向左移动(right -= 1)。
  • 这种方法之所以有效,是因为在任何位置,能够接的雨水量由左边和右边最高的柱子中较低的那个决定。
  • left_maxright_max 保证了不会超过当前位置的最大高度,因此可以安全地计算每个位置的雨水量。

 

class Solution:
    def trap(self, height: List[int]) -> int:
        if not height:
            return 0

        n = len(height)
        left, right = 0, n - 1
        left_max, right_max = height[0], height[n - 1]
        ans = 0

        while left < right:
            if left_max < right_max:
                left += 1
                left_max = max(left_max, height[left])
                ans += max(0, left_max - height[left])
            else:
                right -= 1
                right_max = max(right_max, height[right])
                ans += max(0, right_max - height[right])

        return ans

# 示例用法
sol = Solution()
print(sol.trap([0,1,0,2,1,0,1,3,2,1,2,1]))  # 输出应为 6
print(sol.trap([4,2,0,3,2,5]))               # 输出应为 9

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
代码随想录算法训练营一个优质的学习和讨论平台,提供了丰富的算法训练内容和讨论交流机会。在训练营中,学员们可以通过观看视频讲解来学习算法知识,并根据讲解内容进行刷题练习。此外,训练营还提供了刷题建议,例如先看视频、了解自己所使用的编程语言、使用日志等方法来提高刷题效果和语言掌握程度。 训练营中的讨论内容非常丰富,涵盖了各种算法知识点和解题方法。例如,在第14天的训练营中,讲解了二叉树的理论基础、递归遍历、迭代遍历和统一遍历的内容。此外,在讨论中还分享了相关的博客文章和配图,帮助学员更好地理解和掌握二叉树的遍历方法。 训练营还提供了每日的讨论知识点,例如在第15天的讨论中,介绍了层序遍历的方法和使用队列来模拟一层一层遍历的效果。在第16天的讨论中,重点讨论了如何进行调试(debug)的方法,认为掌握调试技巧可以帮助学员更好地解决问题和写出正确的算法代码。 总之,代码随想录算法训练营一个提供优质学习和讨论环境的平台,可以帮助学员系统地学习算法知识,并提供了丰富的讨论内容和刷题建议来提高算法编程能力。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [代码随想录算法训练营每日精华](https://blog.csdn.net/weixin_38556197/article/details/128462133)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值