再做leetcode42hard题接雨水——双指针法
给定 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
提示:
n == height.length
1 <= n <= 2 * 104
0 <= height[i] <= 105
题目分析
- 问题定义:计算可以接多少水。
- 关键概念:接水量取决于两个相邻柱子之间的较小者。
算法介绍
- 双指针法:使用两个指针分别从数组的开始和结束向中间移动,同时更新左侧和右侧的最高柱子高度。
算法步骤
- 初始化结果变量
ans
为0,表示可以接的水量。 - 初始化两个指针
left
和right
,分别指向数组的开始和结束。 - 初始化两个变量
leftMax
和rightMax
,分别表示左侧和右侧的最高柱子高度。 - 当
left
小于right
时,进行以下操作:- 更新
leftMax
为leftMax
和height[left]
中的较大值。 - 更新
rightMax
为rightMax
和height[right]
中的较大值。 - 如果
leftMax
小于rightMax
,则说明对于位置left
来说,其左侧最高点一定小于右侧真正最高点,所以可以计算接水量,并将left
向右移动。 - 如果
leftMax
不小于rightMax
,则说明对于位置right
来说,其右侧最高点一定小于或等于左侧最高点,所以可以计算接水量,并将right
向左移动。
- 更新
- 返回
ans
,即可以接的水量。
算法流程
具体代码
//双指针法:!!对于位置 i 的接水量取决于其左侧最高点leftMax 和右侧最高点rightMax 中的较小者!!
//使用 height[left] 和 height[right] 更新 leftMax, rightMax
class Solution {
public:
int trap(vector<int>& height) {
int ans = 0;
int left = 0, right = height.size() - 1;
int leftMax = 0, rightMax = 0;
while (left < right) {
leftMax = max(leftMax, height[left]);
rightMax = max(rightMax, height[right]);
if (leftMax < rightMax) {
//若 leftMax < rightMax, 则说明对于位置 left 来说, 已经可以定:其左侧最高点一定小于右侧真正最高点
ans += leftMax - height[left];
++left;
} else {
ans += rightMax - height[right];
--right;
}
}
return ans;
}
};
算法分析
- 时间复杂度:O(n),其中n是数组的长度。
- 空间复杂度:O(1),只需要常数级别的额外空间。
- 易错点:正确理解双指针的移动逻辑,特别是如何根据两侧的高度更新指针。
相似题目
题目 | 链接 |
---|---|
42. 接雨水 | LeetCode |
173. 二进制搜索树迭代器 | LeetCode |
146. LRU缓存机制 | LeetCode |