每日三题-接雨水、柱状图中最大的矩形、每日温度

简介: 每日三题接雨水柱状图中最大的矩形每日温度

接雨水


7081265a3c8c4b438c44a6e7ceef4bb9.png解法一

暴力(按列求)

获取离当前节点最远左右两边比当前节点值大的值height[l],hright[r]

因为决定装水容量的是矮的所以取height[l],hright[r] 中小的那个减去height[i]就是当前节点可以存放的水,然后遍历

class Solution {
    public int trap(int[] height) {
        int res  = 0;
        int len = height.length;
        for(int i = 0;i < len;i++){
            int left = i -1;
            int right = i+1;
            int maxl = i;
            int maxr = i;
            // 找到离当前节点最远的左边比当前节点值大的值
            while(left >= 0){
                if(height[left] > height[maxl]){
                    maxl = left;
                }
                left--;
            }
            //找到离当前节点最远的右边比当前节点值大的值
            while(right < len){
                if(height[right] > height[maxr]){
                    maxr = right;
                }
                right++;
            }
            if(maxl != maxr){
                res = res + Math.min(height[maxl],height[maxr]) - height[i];
            }
        }
        return res;
    }
}

解法二(按行求)

暴力(按行求)

先取得最高高度mH

然后分别求取1~mH行的雨水

每次遍历height数组,如果当前height[i] < nowH(当前行)并且左右两边都有大等于的nowH的那么就可以res++

class Solution {
    public int trap(int[] height) {
        int res  = 0;
        int len = height.length;
        int mH = 0; //保存最大高度
        for(int i = 0;i < len;i++){
            mH = Math.max(height[i],mH);
        }
        for(int i = 1;i <=mH;i++){
            for(int j = 1;j < len-1;j++){
                if(height[j] < i && isHaveLeftIndex(i,j,height) && isHaveRightIndex(i,j,height)){
                    res++;
                }
            }
        }
        return res;
    }
    public Boolean isHaveLeftIndex(int mH,int index,int [] height){
        for(int i = 0;i < index;i++){
            if(height[i] >= mH) return true;
        }
        return false;
    }
    public Boolean isHaveRightIndex(int mH,int index,int [] height){
        for(int i = index+1;i < height.length;i++){
            if(height[i] >= mH) return true;
        }
        return false;
    }
}

解法三

维护两个数组

max_left[i] 保存i左边大于height[i]的值

max_right [i] 保存i右边大于height[i]的值

和解法一类似

class Solution {
    public int trap(int[] height) {
        int res  = 0;
        int len = height.length;
        int[] max_left = new int[len];
        int[] max_right = new int[len];
        for(int i = 1;i < len-1;i++){
            max_left[i] = Math.max(max_left[i-1],height[i-1]);
        }
        for(int i = len -2;i > 0;i--){
            max_right[i] = Math.max(max_right[i+1],height[i+1]);
        }
        for(int i = 1;i < len-1;i++){
            if(max_left[i] > height[i] && max_right[i] > height[i]){
                res = res + Math.min(max_left[i],max_right[i]) - height[i];
            }
        }
        return res;
    }
}

解法四

双指针

维护一个leftMax与rightMax

一个left,一个right同时往中间靠

如果height[left] < height[right] 那么leftMax一定小于rightMax

class Solution {
    public int trap(int[] height) {
        int res  = 0;
        int len = height.length;
        int left = 0;
        int right = len-1;
        int leftMax = 0;
        int rightMax = 0;
        while(left < right){
            leftMax = Math.max(leftMax,height[left]);
            rightMax = Math.max(rightMax,height[right]);
            if(height[left] < height[right]){ 
                res = res + leftMax-height[left];
                left++;
            }else{
                res = res + rightMax-height[right];
                right--;
            }
        }
        return res;
    }
}

解法五

单调栈

维护一个高度递减的单调栈,栈中存的下标

当出现height[i]>height[stack.peek()时并且stack中至少有两个元素,那么就找到了一个可以接雨水的地方,如果栈中只有一个元素那么加上这个元素也只有两个元素不能接雨水

class Solution {
    public int trap(int[] height) {
        int res  = 0;
        int len = height.length;
        Stack<Integer> stack = new Stack<>();
        for(int i = 0;i < len;i++){
            while(!stack.isEmpty() && height[i] > height[stack.peek()]){
                int top = stack.pop();
                if(stack.isEmpty()) break;
                int left = stack.peek();
                res = res + (i - left - 1) * (Math.min(height[left],height[i])-height[top]);
            }
            stack.add(i);
        }
        return res;
    }
}


柱状图中最大的矩形


f2d7df9411ec48b9b062d3650339dc92.png

解法一

暴力

遍历数组,计算以当前height[i]为高的矩形的面积

向左找到最左边大等于height[i]的下标

向右找到最左边大等于height[i]的下标

然后计算面积

class Solution {
    public int largestRectangleArea(int[] heights) {
        int len = heights.length;
        int left = 0;
        int right = 0;
        int res = 0;
        for(int i = 0;i < len;i++){
            left = right = i;
            while(left > 0 && heights[left-1] >= heights[i]){
                left--;
            }
            while(right < len-1 && heights[right+1] >= heights[i]){
                right++;
            }
            res = Math.max(res,(right-left+1)*heights[i]);
        }
        return res;
    }
}

解法二

单调栈

栈中保存递增的height[i]的下标

如果当前height[i]小于height[stack.peek()]那么以height[stack.pop()]为高的面积就能够确定

class Solution {
    public int largestRectangleArea(int[] heights) {
        int len = heights.length;
        int res = 0;
        Stack<Integer> stack = new Stack<>();
        for(int i = 0;i < len;i++){
            while(!stack.isEmpty() && heights[i] < heights[stack.peek()]){
                int top = stack.pop(); // height[top]高度的长方形面积可以确定
                if(stack.isEmpty()){ // 说明top之前的都比heigh[top]高
                    res = Math.max(res,i*heights[top]);
                }else{
                    int left = stack.peek();
                    res = Math.max(res,(i-left-1)*heights[top]);
                }
            }
            stack.add(i);
        }
        //可能还剩下全是递增的
        while(!stack.isEmpty() && -1 < heights[stack.peek()]){
                int top = stack.pop();
                if(stack.isEmpty()){ 
                    res = Math.max(res,len*heights[top]);
                }else{
                    int left = stack.peek();
                    res = Math.max(res,(len-left-1)*heights[top]);
                }
        }
        return res;
    }
}


每日温度


31e73ecf33b84c458824224ac3f29918.png

解法一

暴力遍历

class Solution {
    public int[] dailyTemperatures(int[] temperatures) {
        int len = temperatures.length;
        if(len == 0) return null;
        int[] ans = new int[len];
        for(int i = 0;i < len ;i++){
            for(int j = i+1;j < len;j++){
                if(temperatures[j] > temperatures[i]){
                    ans[i] = j-i;
                    break;
                }
            }
        }
        return ans;
    }
}

解法二

单调栈

维护一个温度单调递减的栈

如果temperatures[i] > temperatures[stack.peek()]则找到下标为stack.peek()的下一个更高温度

class Solution {
    public int[] dailyTemperatures(int[] temperatures) {
        int len = temperatures.length;
        if(len == 0) return null;
        Stack<Integer> stack = new Stack<>();
        int[] ans = new int[len];
        for(int i = 0;i < len ;i++){
            while(!stack.isEmpty() && temperatures[i] > temperatures[stack.peek()] ){
                int top = stack.pop();
                ans[top] = i-top;
            }
            stack.add(i);
        }
        return ans;
    }
}
相关文章
|
算法 测试技术 图计算
|
Serverless C语言 C++
【数学建模】利用C语言来实现 太阳赤纬 太阳高度角 太阳方位角 计算和求解分析 树木树冠阴影面积与种植间距的编程计算分析研究
【数学建模】利用C语言来实现 太阳赤纬 太阳高度角 太阳方位角 计算和求解分析 树木树冠阴影面积与种植间距的编程计算分析研究
237 1
一个球从 1000 米高空掉落,每次弹起高度是上一次的 50% ,弹几次后,高度低于 1 米
一个球从 1000 米高空掉落,每次弹起高度是上一次的 50% ,弹几次后,高度低于 1 米
65 0
|
数据挖掘
这图怎么画| 箱线图+散点+中位数连线
这图怎么画| 箱线图+散点+中位数连线
125 0
代码随想录刷题|LeetCode 503.下一个更大元素II 42. 接雨水 84.柱状图中最大的矩形
代码随想录刷题|LeetCode 503.下一个更大元素II 42. 接雨水 84.柱状图中最大的矩形
代码随想录刷题|LeetCode 503.下一个更大元素II 42. 接雨水 84.柱状图中最大的矩形
|
索引 容器
42.接雨水
42.接雨水
74 0
42.接雨水
L1-060 心理阴影面积 (5 分)
L1-060 心理阴影面积 (5 分)
308 0
L1-060 心理阴影面积 (5 分)