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
-
初始化:创建一个栈来保存索引,一个数组
result
来存储结果,初始时该数组的所有值设为 -1(表示没有找到下一个更大的元素)。 -
双重遍历:由于这是一个循环数组,我们需要遍历两次数组。第一次遍历找到每个元素右侧的第一个更大的元素,第二次遍历用来找到那些在数组末尾但它们的更大元素在数组开头的情况。
-
栈的使用:在遍历的过程中,每次我们考察一个新元素时,我们检查栈顶元素代表的数组值是否小于当前元素。如果是,则我们找到了栈顶元素的下一个更大元素。我们在
result
数组的相应位置记录这个更大元素,然后将栈顶元素弹出。这个过程一直持续到栈为空或者栈顶元素代表的数组值大于等于当前元素。之后,将当前元素的索引压入栈中。 -
循环:由于数组是循环的,我们可以通过取模操作来模拟数组的循环。
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
在接雨水问题中,双指针法的核心思想是同时从数组的两端开始遍历,使用两个指针(left
和 right
),分别代表数组的左端和右端。在这个过程中,我们维护两个变量(left_max
和 right_max
),它们分别表示遍历到目前为止左侧和右侧遇到的最大高度。这样,我们可以在每个步骤中确定当前位置能够接收的雨水量。
-
初始化指针和变量:
left = 0
(数组的开始位置)right = len(height) - 1
(数组的结束位置)left_max = height[0]
right_max = height[len(height) - 1]
-
遍历数组:
- 使用两个指针从两端开始遍历数组,直到它们相遇。
- 在每个位置,更新
left_max
和right_max
。
-
比较
left_max
和right_max
:- 如果
left_max < right_max
,则说明左边的柱子是短板,处理左边的柱子。 - 否则,处理右边的柱子。
- 如果
-
计算雨水量并累加:
- 对于左边的柱子:
left_max
是左边最高的柱子,height[left]
是当前柱子的高度,因此在位置left
上的雨水量是left_max - height[left]
。 - 对于右边的柱子:同理,使用
right_max - height[right]
来计算雨水量。 - 将计算出的雨水量累加到总量中。
- 对于左边的柱子:
-
移动指针:
- 如果处理的是左边的柱子,将
left
指针向右移动(left += 1
)。 - 如果处理的是右边的柱子,将
right
指针向左移动(right -= 1
)。
- 如果处理的是左边的柱子,将
- 这种方法之所以有效,是因为在任何位置,能够接的雨水量由左边和右边最高的柱子中较低的那个决定。
left_max
和right_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