如何高效解决接雨水问题 :: labuladong的算法小抄 #1033
Replies: 20 comments 6 replies
-
第二题建议补一下正确性证明 |
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.
-
接雨水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.
-
文章链接点这里:如何高效解决接雨水问题
评论礼仪 见这里,违者直接拉黑。
Beta Was this translation helpful? Give feedback.
All reactions