• LeetCode42-接雨水


    题目描述

    给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

    我的题解

    关键在于找到全部可以装雨水的'槽'
    从第一个柱子开始,寻找第一个比它高的,即可组成一个槽。
    如果没有更高的,就找到后面最高的,这时也可以组成一个槽

        //99.98%
        public int trap(int[] height) {
            int len = height.length;
            int rainCount = 0;//雨量
            for (int i=0;i<len-1;i++){
                if (height[i+1]>height[i])continue;//如果这个柱子比下一个低,跳过。
                int highter = height[i];//后面更高的柱子高度
                int highterIndex = i;//后面更高的柱子索引
                int max = height[i+1];//后面的最高柱子
                int maxIndex = i+1;//后面的最高柱子索引
                boolean hasHighter = false;//后面是否存在比当前柱子更高的柱子
                for (int j=i+1;j<len;j++){
                    if (height[j]>=highter){//找到不低于当前柱子的柱子
                        highterIndex = j;
                        hasHighter = true;
                        break;
                    }
                    if (height[j]>max){//计算后面最高的
                        max = height[j];
                        maxIndex = j;
                    }
                }
                if (!hasHighter) {//如果后面没有更高的柱子,就是用后面的最高柱子
                    highterIndex = maxIndex;
                    highter = max;
                }
                for (int j=i+1;j<highterIndex;j++){//计算这个槽可以积累的雨量
                    rainCount+=highter-height[j];
                }
                i=highterIndex-1;//跳到这个槽的右边柱子
            }
            return rainCount;
        }
    

    分析:
    时间复杂度:O(N),虽然看似有来两个循环,但是他们是线性的
    空间复杂度: O(1),只使用了几个变量而已

    其他解法

    单调栈

    public class Solution {
        public int trap(int[] height) {
            if (height == null) {
                return 0;
            }
            Stack<Integer> stack = new Stack<>();
            int ans = 0;
            for (int i = 0; i < height.length; i++) {
                while(!stack.isEmpty() && height[stack.peek()] < height[i]) {
                    int curIdx = stack.pop();
                    // 如果栈顶元素一直相等,那么全都pop出去,只留第一个。
                    while (!stack.isEmpty() && height[stack.peek()] == height[curIdx]) {
                        stack.pop();
                    }
                    if (!stack.isEmpty()) {
                        int stackTop = stack.peek();
                        // stackTop此时指向的是此次接住的雨水的左边界的位置。右边界是当前的柱体,即i。
                        // Math.min(height[stackTop], height[i]) 是左右柱子高度的min,减去height[curIdx]就是雨水的高度。
                        // i - stackTop - 1 是雨水的宽度。
                        ans += (Math.min(height[stackTop], height[i]) - height[curIdx]) * (i - stackTop - 1);
                    }
                }
                stack.add(i);
            }
            return ans;
        }
    }
    
  • 相关阅读:
    C++中 destory() 和deallocate()以及delete函数的相关性和区别性
    由STL所想到的 C++显示调用析构函数
    MINIX3 内核整体架构回顾及内核定 性分析
    有一个无效 SelectedValue,因为它不在项目列表中
    SqlParameter.Value = NULL 引发的数据库异常
    前端解决跨域问题的8种方案(最新最全)
    SQL语句优化技术分析 整理他人的
    暂时未整理 已打印
    .Net_把文件数据添加到数据库中(面试题)
    ASP.NET中application对象的用法(面试题)
  • 原文地址:https://www.cnblogs.com/XT-xutao/p/12633043.html
Copyright © 2020-2023  润新知