如何高效解决接雨水问题 :: labuladong的算法小抄 #1033
Replies: 20 comments 6 replies
-
|
Beta Was this translation helpful? Give feedback.
-
第二题建议补一下正确性证明 |
Beta Was this translation helpful? Give feedback.
-
第二题,如果 height[left]==height[right] 如何判断是需要移动left 还是移动right 才会出现最优解呢? |
Beta Was this translation helpful? Give feedback.
-
@bigyou 相等的话左移右移都可以,因为中间部分的面积肯定没有这两个相等的柱子围成的面积大 |
Beta Was this translation helpful? Give feedback.
-
打卡 |
Beta Was this translation helpful? Give feedback.
-
接雨水js版 /**
* @param {number[]} height
* @return {number}
*/
var trap = function (height) {
// 想找到第i个柱子上可以接多少雨水 res[i]
// 先找到右边最高的柱子max_l 找到左边最高的柱子max_r 取min(l,r)-height[i] = res[i]
// 使用备忘录优化
const m = height.length;
let max_l = Array(m), max_r = Array(m);
let res = 0, temp;
// 初始化base case
max_l[0] = height[0];
max_r[m - 1] = height[m - 1];
// max_l[i] 代表第i个柱子左边最大高度是多少
// 按照这个思路把max_l 和max_r 初始化 这块不懂可以画画这个步骤的图就懂了
for (let i = 1; i < m; i++)
max_l[i] = Math.max(height[i], max_l[i - 1]);
for (let i = m - 2; i >= 0; i--)
max_r[i] = Math.max(height[i], max_r[i + 1]);
for (let i = 0; i < m; i++) {
temp = Math.min(max_l[i], max_r[i]) - height[i];
res += temp > 0 ? temp : 0;
}
return res;
}; |
Beta Was this translation helpful? Give feedback.
-
打卡,感谢楼主! |
Beta Was this translation helpful? Give feedback.
-
第一题的备忘录解法,也应该判断min(left_max, right_max)是否大于当前柱子的高度吧?假如min(left_max, right_max)是3,但当前柱子是5,直接相减得-2了,然而应当是0。 |
Beta Was this translation helpful? Give feedback.
-
第一题为什么移动较矮的指针呢?好难想到。。 |
Beta Was this translation helpful? Give feedback.
-
check in |
Beta Was this translation helpful? Give feedback.
-
@saw008 审题
所以两个max至少是当前柱子height,所以差最小是0 |
Beta Was this translation helpful? Give feedback.
-
打卡。左右两边双指针 |
Beta Was this translation helpful? Give feedback.
-
听说这是 tiktok 的面试题 🤫 |
Beta Was this translation helpful? Give feedback.
-
好神奇啊,两道题都能看懂解法,但好像一下子看不出来区别 |
Beta Was this translation helpful? Give feedback.
-
其实可以这么理解, 初始的想法是求 minmax(l_height, r_height), 但只要存在某个 r_height > l_max, 那么即使 r_height 不是 r_max, 我们也只能选择 l_max |
Beta Was this translation helpful? Give feedback.
-
第二道题这样写,可以减少计算次数
|
Beta Was this translation helpful? Give feedback.
-
接雨水, O(N), Python, 不需要用双指针 class Solution:
def trap(self, height: List[int]) -> int:
"""
一般地, 高度为h的格子, 接雨水量 = max(0, min(l_max, r_max) - h),
其中l_max, r_max分别为它的左右两半的最大高度.
现找到整个数组中高度最高的地方, 分成两半.
对于左半边, min(l_max, r_max)一定是l_max.
因此只需顺序遍历, 维护当前看过的最高高度hmax, 若当前高度h小于它, 则可以接雨水hmax - h
对于右半边, 可以反转一下然后当左半边处理
"""
def calculate(arr):
res = 0
hmax = 0
for h in arr:
if h < hmax:
res += hmax - h
else:
hmax = h
return res
i = height.index(max(height))
return calculate(height[:i]) + calculate(height[i+1:][::-1]) |
Beta Was this translation helpful? Give feedback.
-
可以,因为本题中竖线没有宽度,所以 left 和 right 之间能够盛的水就是: |
Beta Was this translation helpful? Give feedback.
-
42 接雨水双指针算法,while (left < right) 语句等价于 while (left <= right) 语句。因为 left, right 一定相遇于最高柱子,即当 left == right 时,必有 height[left] == max(height[0..n - 1])。而最高柱子的接水量为 0,所以累加计算 left == right 时的最高柱子的接水量。 虽然二者效果等价,但后者更直观易懂。 |
Beta Was this translation helpful? Give feedback.
-
其实双指针的循环结束条件分析,left<right和left<=right并不影响,因为最后一步一定是max-max,不能盛水的。 |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
文章链接点这里:如何高效解决接雨水问题
评论礼仪 见这里,违者直接拉黑。
Beta Was this translation helpful? Give feedback.
All reactions