题目分析
首先题目在这里:LeetCode 接雨水
这道题的热门和经典程度可以借用某一条评论:
据说字节的清洁工阿姨和保安大叔都会做这个题。
做题这件事情虽然有些刻苦用功的意思在,很难说得上轻松愉快,不过在某一些题目的解法中,那些灵光一闪的题解,真的能让人豁然开朗和智力的光。
这道题也让我有这种感觉,来自这张图
小时候经常对一些题有一些冒出来的巧妙的解法,大概就是那种感觉。
动态规划解法
动态规划解法就是上面这张图。
针对这张图,从左往右所有浅绿色的部分是;
1 |
|
从右往左所有浅红色的部分是:
1 |
|
那么可得交叠的部分为:
1 |
|
最后得到合并方法
1 |
|
这个方法的优势,特别的好理解,劣势,提交之后大概率排名垫底。
双指针
双指针是针对dp方法的优化。
1 |
|
单调栈
题解中的单调栈描述的不清楚,没有描述关键的入栈和出栈条件。
解题思路是:
利用栈维护高度单调递减(不严格)的柱子下标,这实际上是在维护一个下凹的区域,一旦发现栈顶的元素小于最新的元素,那就意味着找到了一个小小的凹进去的区域。
需要注意的是这个区域可能只是一个大区域中的小部分。
比如柱子的高度是 5,4,3,2,3,5,当遍历到第二个3的时候,实际上我们找到的凹进去的区域时323这一段,实际上两个5之间都是连续的凹进去的。
不过不要担心,当遍历到第二个5的时候,只要明确两个5之间没被计算的部分是 4*2=8就可以了。
一段凹进去的区域之间的积水量始终为:
Math.min(height[concurrent], height[left])-height[top] * (concurrent-top-1)
入栈条件:
- 当前柱子的高度不大于栈顶柱子的高度时,将当前柱子下标入栈
- 保持栈中的高度是递减的
出栈条件:
- 当前柱子的高度大于栈顶柱子的高度时,栈顶柱子出栈
- 通过出栈操作找到能够形成的积水区域,计算雨水量
1 |
|