单调栈结构(也会涉及一些别的知识)(利口 讲的很好)

Leetcode42 接雨水
题目:在这里插入图片描述
方法1: 求每一列的,遍历每个列,当前列只和她左边的最大值以及右边的最大值有关系,因为木桶效应。

class Solution {
    public int trap(int[] height) {
        //两端一定没水,因为他们
        int res=0;
        for(int i=1;i<height.length-1;i++){
            //找左边的最大高度
            int left=i-1;
            int maxL=0;
            while(left>=0){
                maxL=Math.max(maxL,height[left--]);
            }
            //求右边的最大值
            int maxR=0;
            int right=i+1;
            while(right<height.length){
                maxR=Math.max(maxR,height[right++]);
            }
            int max=Math.min(maxR,maxL);
            res=res+(max-height[i]>0?max-height[i]:0);
        }
        return res;
    }
}

方法2:动态规划,或者说是数组预处理

class Solution {
    public int trap(int[] height) {
        int res=0;
        //动态规划||或者叫数组初始化
        //初始化左高数组   最左边和最右边的left和right值都是0,因为没有了,因为初始化就是0,所以i从1开始就额可以
        int[] left=new int[height.length];
        for(int i=1;i<height.length;i++){
            left[i]=Math.max(height[i-1],left[i-1]);
        }
        //初始化右高数组
        int[] right=new int[height.length];
        for(int i=height.length-2;i>=0;i--){
            right[i]=Math.max(right[i+1],height[i+1]);
        }
        for(int i=1;i<height.length-1;i++){
            int temp=Math.min(left[i],right[i]);
            res=res+((temp-height[i])>0?(temp-height[i]):0);
        }
        return res;
    }
}

方法3:单调栈,单调栈就是可以on找左右的最靠近的最大值和最小值(基本作用),但是这个题不是哦,,,

class Solution {
    public int trap(int[] height) {
        if(height==null||height.length==0||height.length==1){
            return 0;
        }
        int res=0;
        //单调栈法,首先分析是维护单调递减栈还是单调递增栈
        //这个题无论从左还是右都要维护单调递减栈
        Stack<Integer> stack=new Stack();
        int cur=1;
        stack.push(0);
        while(!stack.isEmpty()&&cur<height.length){
            while(height[cur]>height[stack.peek()]){
                int h=height[stack.peek()];
                stack.pop();
                if(stack.isEmpty()){
                    break;
                }
                res=res+(Math.min(height[stack.peek()],height[cur])-h)*(cur-stack.peek()-1);
            }
            stack.push(cur);
            cur++;
        }
        return res;
    }
}

Leetcode46:下一个更大元素
其实就是建立一个单调递减栈,这样遇到大的就弹,弹的时候,标记他的右最大就是遇到这个

class Solution {
    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
        Map<Integer, Integer> map = new HashMap<>();
        Deque<Integer> stack = new ArrayDeque<>();
        int[] greater = new int[nums1.length];
        for (int num : nums2) {
            while (!stack.isEmpty() && stack.peek() < num)
                map.put(stack.pop(), num);
            stack.push(num);
        }
        while (!stack.isEmpty())
            map.put(stack.pop(), -1);
        
        for (int i = 0; i < nums1.length; i++) 
            greater[i] = map.get(nums1[i]);
        
        return greater;
    }
}

leetcode 503下一个最大元素2:和1 的不同就是在于循环数组的处理,其他都一样
方法1,69ms,很慢,但是我确实是on时间复杂度

class Solution {
    public int[] nextGreaterElements(int[] nums) {
        Map<Integer,Integer> map=new HashMap();//这个存放的是下标和对应的右边最大值
        int n=nums.length;
        Stack<Integer> st=new Stack();
        int[] res=new int[nums.length];
        for(int i=0;i<=nums.length*2-1;i++){
            //构建一个单调递减的站
            while(!st.isEmpty()&&nums[i%n]>nums[st.peek()]){
                map.putIfAbsent(st.pop(),nums[i%n]);
            }
            st.push(i%n);
        }
        while(!st.isEmpty()){
            map.putIfAbsent(st.pop(),-1);
        }
        for(int i=0;i<n;i++){
            res[i]=map.get(i);
        }
        return res;
    }
}

方法2:暴力法,注意越界问题

class Solution {
    public int[] nextGreaterElements(int[] nums) {
        //暴力法,就是从头找
        int[] res=new int[nums.length];
        for(int i=0;i<nums.length;i++){
            int j=(i+1)%nums.length;
            while(j!=i){
                if(nums[j]>nums[i]){
                    res[i]=nums[j];
                    break;
                }
                j=(j+1)%nums.length;//这里注意
            }
            if(j%nums.length==i){
                res[i]=-1;
            }
        }
        return res;
    }
}

leetcode739 每日温度

//原始版本,魔板套用版
class Solution {
    public int[] dailyTemperatures(int[] T) {
        //很简单就是维护一个单调递减栈
        Stack<Integer> st=new Stack();
        int[] res=new int[T.length];
        int[] res1=new int[T.length];
        for(int i=0;i<T.length;i++)
        {
            while(!st.isEmpty()&&T[i]>T[st.peek()]){
                res[st.pop()]=i;
            }
            st.push(i);
        }
        while(!st.isEmpty()){
            res[st.peek()]=st.pop();
        }
        for(int i=0;i<T.length;i++){
            res1[i]=res[i]-i;
        }
        return res1;
    }
}

魔板‘:

class Solution {
    public int[] dailyTemperatures(int[] T) {
        //很简单就是维护一个单调递减栈
        Stack<Integer> st=new Stack();
        int[] res=new int[T.length];//存放每个下标对应的左边的第一个最大值的数组
        for(int i=0;i<T.length;i++)
        {
        //魔板话语句start
            while(!st.isEmpty()&&T[i]>T[st.peek()]){
                res[st.pop()]=i;
            }
            st.push(i);
        }
        while(!st.isEmpty()){
            res[st.peek()]=st.pop();
        }
        //魔板结束,致辞已经把所有的点的第一个大于他的元素弄好了
        return res1;
    }
}

改进:
我不知道为什么明明少了for,为什么时间还多了?????,上面是40ms多
这个是50多ms,我也是醉了。。。

class Solution {
    public int[] dailyTemperatures(int[] T) {
        //很简单就是维护一个单调递减栈
        Stack<Integer> st=new Stack();
        int[] res=new int[T.length];
        for(int i=0;i<T.length;i++)
        {
            while(!st.isEmpty()&&T[i]>T[st.peek()]){
                res[st.peek()]=i-st.peek();
                st.pop();
            }
            st.push(i);
        }
        return res;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值