• LeetCode


    链接:https://leetcode.cn/problems/trapping-rain-water/solution/san-chong-by-xun-ge-v-3op9/
    来源:力扣(LeetCode)
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 

    题目

     

    示例

     

    思路

    解题思路

    1. 动态规划

    使用动态规划思路,就是对暴力求解进行优化过程,定义两个dp数组,一个保存左边最大值,一个保存右边最大值,遍历数组枚举每一个元素与对应左边和右边最大值的大小情况

    • 当前元素与左边和右边最大值都小,说明此处可以存水
    • 当前元素与左边或右边最大值小,说明此处可以不能存水,因为有一边会漏


    具体实现看下面代码,有注释

    使用单调递减栈
    理解题目,参考图解,注意题目的性质,当后面的柱子高度比前面的低时,是无法接雨水的
    当找到一根比前面高的柱子,就可以计算接到的雨水
    所以使用单调递减栈对更低的柱子入栈
    更低的柱子以为这后面如果能找到高柱子,这里就能接到雨水,所以入栈把它保存起来
    平地相当于高度 0 的柱子,没有什么特别影响
    当出现高于栈顶的柱子时
    说明可以对前面的柱子结算了
    计算已经到手的雨水,然后出栈前面更低的柱子

    计算雨水的时候需要注意的是
    雨水区域的右边 r 指的自然是当前索引 i
    底部是栈顶 st.top() ,因为遇到了更高的右边,所以它即将出栈,使用 cur 来记录它,并让它出栈
    左边 l 就是新的栈顶 st.top()
    雨水的区域全部确定了,水坑的高度就是左右两边更低的一边减去底部,宽度是在左右中间
    使用乘法即可计算面积

    具体实现看下面代码,有注释

    1. 双指针

    双指针思路与动态规划差不多


    具体实现看下面代码,有注释

    代码

    动态规划

    1. //动态规划
    2. #define MAX(a , b) ((a) > (b) ? (a) : (b))
    3. int trap(int* height, int heightSize){
    4. int dpLeft[heightSize];//定义左边最大值
    5. dpLeft[0] = height[0];
    6. int dpRight[heightSize];//定义右边最大值
    7. dpRight[heightSize-1] = height[heightSize-1];
    8. int conut = 0;
    9. for(int i = 1; i < heightSize; i++)//单指针,线性扫描
    10. {
    11. dpLeft[i] = MAX(dpLeft[i-1] , height[i]);//保存左边最大值
    12. dpRight[heightSize - i - 1] = MAX(dpRight[heightSize - i] , height[heightSize - 1 - i]);//保存右边最大值
    13. }
    14. for(int i = 0; i < heightSize; i++)//遍历dp数组
    15. {
    16. if(height[i] >= dpLeft[i] || height[i] >= dpRight[i])
    17. {
    18. continue;
    19. }
    20. int min = dpLeft[i] < dpRight[i] ? dpLeft[i] : dpRight[i];//保存最小边
    21. conut += min - height[i]; //保存雨水
    22. }
    23. return conut;
    24. }
    25. 作者:xun-ge-v
    26. 链接:https://leetcode.cn/problems/trapping-rain-water/solution/san-chong-by-xun-ge-v-3op9/
    27. 来源:力扣(LeetCode)
    28. 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    1. //栈
    2. int trap(int* height, int heightSize) {
    3. int n = heightSize;
    4. if (n == 0) {
    5. return 0;
    6. }
    7. int ans = 0;
    8. int stk[n], top = 0;//初始化变量
    9. for (int i = 0; i < n; ++i) {//遍历数组
    10. while (top && height[i] > height[stk[top - 1]]) {//栈不为空,并当前元素将破坏栈的递减性,将栈元素弹出,直达维护栈递减
    11. int stk_top = stk[--top];//弹出栈顶元素
    12. if (!top) {//弹出后栈为空,说明两个元素挨在一起,肯定存不了水,
    13. break;
    14. }
    15. int left = stk[top - 1];//取左边界
    16. int currWidth = i - left - 1;
    17. int currHeight = fmin(height[left], height[i]) - height[stk_top];//计算高和底
    18. ans += currWidth * currHeight;//保存水面积,如果此时栈还是未递减,继续弹出元素
    19. }
    20. stk[top++] = i;
    21. }
    22. return ans;
    23. }
    24. 作者:xun-ge-v
    25. 链接:https://leetcode.cn/problems/trapping-rain-water/solution/san-chong-by-xun-ge-v-3op9/
    26. 来源:力扣(LeetCode)
    27. 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    双指针

    1. //双指针
    2. int trap(int* height, int heightSize){
    3. int leftMax = -1;
    4. int rightMax = -1;
    5. int left = 0;
    6. int right = heightSize - 1;
    7. int conut = 0;//定义初始化变量
    8. while(left < right)//左右遍历数组
    9. {
    10. if(height[left] < height[right])//右边高
    11. {
    12. if(height[left] >= leftMax)//当前更高,肯定存不水
    13. {
    14. leftMax = height[left];
    15. }
    16. else//比左边最大值小,并且左边比右边小,所以此处肯定是底处,下同,只是反过来
    17. {
    18. conut += leftMax - height[left];
    19. }
    20. left++;
    21. }
    22. else//左边高
    23. {
    24. if(height[right] >= rightMax)
    25. {
    26. rightMax = height[right];
    27. }
    28. else
    29. {
    30. conut += rightMax - height[right];
    31. }
    32. right--;
    33. }
    34. }
    35. return conut;
    36. }
    37. 作者:xun-ge-v
    38. 链接:https://leetcode.cn/problems/trapping-rain-water/solution/san-chong-by-xun-ge-v-3op9/
    39. 来源:力扣(LeetCode)
    40. 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  • 相关阅读:
    三菱Q系列PLC远程调试并实现4G/5G数据通讯?
    前端有哪些好的学习网站?
    Spring Boot集成WebSocket实现消息推送
    Vue3.2插槽全家桶
    【FNN回归预测】基于matlab蝙蝠算法优化前馈神经网络数据回归预测【含Matlab源码 2070期】
    [BUUCTF newstar week2] crypto/pwn/reverse
    S32DS踩坑日记五-bootloader跳转APP时触发DefaultISR
    计算机网络-DNS以及FastGitHub
    【GAN】数据增强基础知识
    【广州华锐互动】智能变电站AR仿真实训系统大大提高培训的效率和质量
  • 原文地址:https://blog.csdn.net/m0_64560763/article/details/126099218