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

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

接雨水


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;
    }
}
相关文章
|
7月前
GEE中如何制作多线段图表?以气象数据中气温、风速和气压制作时序图表为例
GEE中如何制作多线段图表?以气象数据中气温、风速和气压制作时序图表为例
87 0
|
物联网 Linux Android开发
圆曾经的小车梦,造一台智能小车(一)
圆曾经的小车梦,造一台智能小车(一)
116 1
Threejs实现模拟河流,水面水流,水管水流,海面
Threejs实现模拟河流,水面水流,水管水流,海面
2447 0
Threejs实现模拟河流,水面水流,水管水流,海面
基于三相坐标系状态方程的感应电动机起动动态计算(Matlab代码实现)
基于三相坐标系状态方程的感应电动机起动动态计算(Matlab代码实现)
|
7月前
[贴装专题] 基于halcon的最小二乘法计算吸嘴或机械轴旋转中心
[贴装专题] 基于halcon的最小二乘法计算吸嘴或机械轴旋转中心
209 0
|
传感器 IDE 开发工具
圆曾经的小车梦,造一台智能小车(二)
圆曾经的小车梦,造一台智能小车(二)
135 1
|
传感器
有刷无刷,永磁同步,步进,空心杯,统统拆开看看有什么不同
有刷无刷,永磁同步,步进,空心杯,统统拆开看看有什么不同
|
机器学习/深度学习 传感器 人工智能
【物理应用】基于Zernike多项式的大气湍流相位屏的数值模拟附matlab代码
【物理应用】基于Zernike多项式的大气湍流相位屏的数值模拟附matlab代码
|
编解码 算法 BI
地表净辐射通量数据、太阳辐射量数据、降雨量数据、气温数据、日照时长、水汽压分布、风速风向数据、地表温度
地表净辐射通量数据、太阳辐射量数据、降雨量数据、气温数据、日照时长、水汽压分布、风速风向数据、地表温度
地表净辐射通量数据、太阳辐射量数据、降雨量数据、气温数据、日照时长、水汽压分布、风速风向数据、地表温度