【每日算法】队 栈| day4

239.滑动窗口最大值

 代码逻辑:

变量:构造一个双端队列 , 构建存储最大值的数组

边界情况:传进来的为空,两个都要判断

构造双端队列,存储最大值数组

遍历前三个:初始化双端队列,数组的前三个,按照规则入队

        while条件:队列不为空,且队尾元素 小于 数组当前值

        while执行:移除队尾元素

将数组当前值加到队尾

结果的第一个存放队头 元素

循环:让滑动窗口滑动,进行相关规则的入队出队操作,其中每判断一次,存一次结果

        1.判断:滑动窗口滑出去的元素 是否在队首 ----  如果在,从队头移除

        

       2. while条件:队列不为空,且队尾元素 小于 数组当前值

        while执行:移除队尾元素

        3.将当前数组值加入队尾

                结果存储队头元素

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        if(nums.length == 0 || k == 0 ) return new int[0];

        Deque<Integer> deque = new LinkedList<>();
        int[] res = new int[nums.length - k + 1];

        for(int i = 0 ; i < k ; i++){
            while( !deque.isEmpty() && deque.peekLast() < nums[i]){
                deque.removeLast();
            }
            deque.addLast(nums[i]);
        }
        res[0] = deque.peekFirst();

        for(int i = k ; i < nums.length ; i++){
            if(deque.peekFirst() == nums[i - k]){
                deque.removeFirst();
            }

            while( !deque.isEmpty() && deque.peekLast() < nums[i]){
                deque.removeLast();
            }

            deque.addLast(nums[i]);
            res[i - k + 1] = deque.peekFirst();
        }

        return res;
    }
}

42.接雨水

 

一个凹槽是由三个柱子围成的  ----  边界条件 --- 只有两个元素是构不成凹槽的

变量:栈(用来存储对应的柱子的下标 --- 不是存高度),结果值

遍历数组:

三种情况:栈空 --- 直接压栈 ,当前高度小于等于栈顶元素高度 --- 直接压栈

                当前高度高于栈顶元素高度  ---  可以进行计算凹槽的标志

                        当前栈顶元素 为 凹槽底部

                        while条件:栈不空 ,且当前高度 大于 栈顶元素  --- 一直有凹槽存在,一直弹出

                        while执行:高度为当前高度 和 栈顶元素 高度的最小值, 减去凹槽底部高度

                                            宽度为当前下标值 减去 栈顶元素 的下标值 减一

                                                结果累加面积

class Solution {
    public int trap(int[] height) {
        if(height.length <= 2) return 0;

        Stack<Integer> stack = new Stack<Integer>();
        int res = 0;

        for(int i = 0 ; i < height.length ; i++){
            if(stack.isEmpty()){
                stack.push(i);
            } else if (height[i] <= height[stack.peek()]){
                stack.push(i);
            } else {
                while(!stack.isEmpty() && height[i] > height[stack.peek()]){
                    int bottom = stack.peek();
                    stack.pop();

                    if(!stack.isEmpty()){
                        int h = Math.min(height[i],height[stack.peek()]) - height[bottom];
                        int w = i - stack.peek() - 1;
                        res += h * w;
                    }
                }
                stack.push(i);
            }
        }
        return res;
    }
}

       少一层判断                 

while当前高度高于栈顶元素高度  ---  可以进行计算凹槽的标志

获取bottom

        if  栈不空

                获取高和宽,计算面积

641.设计循环双端队列

        就是循环队列的理论实现

class MyCircularDeque {

    private int capacity ;
    private int front;
    private int rear;
    private int[] arr;


    public MyCircularDeque(int k) {
        capacity = k + 1;
        arr = new int[capacity];
        front = 0;
        rear = 0;
    }

    public boolean insertFront(int value) {

        if(isFull()){
           return false;
        }

        front = ( front - 1  + capacity) % capacity;
        arr[front] = value;
        return true;

    }

    public boolean insertLast(int value) {
        if(isFull()){
           return false;
        }

        arr[rear] = value;
        rear = ( rear + 1 ) % capacity;
        return true;

    }
    
    public boolean deleteFront() {
        if(isEmpty()){
            return false;
        }

        front = ( front + 1 ) % capacity;
        return true;

    }

    public boolean deleteLast() {
        if(isEmpty()){
            return false;
        }

        rear = ( rear - 1 + capacity ) % capacity;
        return true;
    }
    
    public int getFront() {
        if(isEmpty()){
            return -1;
        }

        return arr[front];

    }
    
    public int getRear() {
        if(isEmpty()){
            return -1;
        }

        return arr[(rear - 1 + capacity) % capacity];
    }
    
    public boolean isEmpty() {
        return front == rear;
    }
    
    public boolean isFull() {
        return ( rear + 1 ) % capacity == front;
    }
}

这两的添加顺序是不同的,所以后来得到的元素有问题;

85.最大矩形

演变于 84.柱状图中最大的矩形

是其 的二维画

最大值 ---- Math.max()

 每一行转化为高度值

代码逻辑:

变量:设置高度数组 --- 长度为列数,  最大值

遍历每行每列,如果是1 ,则高度矩阵加1

复用84题代码

class Solution {
    public int maximalRectangle(char[][] matrix) {
        int[] heights = new int[matrix[0].length];
        int maxArea = 0;

        for(int row = 0 ; row < matrix.length ; row++){
            for(int col = 0 ; col < matrix[0].length ; col++){
                if(matrix[row][col] == '1'){
                    heights[col] += 1;
                } else {
                    heights[col] = 0;
                }
            }

            maxArea = Math.max(maxArea,largestRectangleArea(heights));
        }
        return maxArea;
    }

     public int largestRectangleArea(int[] heights) {
        int res = 0;
        Stack<Integer> stack = new Stack<Integer>();

        int[] newHeight = new int[heights.length + 2];
        newHeight[0] = 0;
        newHeight[newHeight.length - 1] = 0;

        for(int i = 1; i < heights.length + 1 ; i++){
            newHeight[i] = heights[i - 1];
        }

        

        for(int i = 0 ; i < newHeight.length; i++){
            while(!stack.isEmpty() && newHeight[i] < newHeight[stack.peek()]){
                int cur = stack.pop();
                int curHeight = newHeight[cur];

                int leftIndex = stack.peek();
                int rightIndex = i;
                int curWidth = rightIndex - leftIndex - 1;

                res = Math.max(res, curHeight * curWidth);
            }
            stack.push(i); 
        }

        return res;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值