Day20-代码随想录-逆波兰表达式求值150+滑动窗口最大值239

逆波兰表达式求值150题目如下所示:

这道题不难,能一下子想到使用栈去操作,自己主要的纠结点在怎么把字符串的运算符提取为真的运算符,我这死脑筋,题目已经明确说明了有效的算符为+-*/,我还在思考要是用判断语句无法判断完所有的运算符(比如什么逻辑运算符等),所以其实直接用if-else来匹配即可,注意这里的"+"是字符串,不能用==来判断,得用"+".equals(s)来判断。

代码如下:

class Solution {
    public int evalRPN(String[] tokens) {
       Deque<Integer> stack = new LinkedList<>();
       //用栈的方式来解决,将数字先压入,一遇到运算符,将相邻的两个栈顶取出,
       //计算出结果后又将值压入栈,以此反复
       for(String s : tokens){
            if("+".equals(s)){
                stack.push(stack.pop() + stack.pop());
            }else if("-".equals(s)){
                stack.push(-stack.pop() + stack.pop());//-和/需要进行特殊处理
            }else if("*".equals(s)){
                stack.push(stack.pop() * stack.pop());
            }else if("/".equals(s)){
                int temp1 = stack.pop();
                int temp2 = stack.pop();
                stack.push(temp2/temp1);
            }else{
                stack.push(Integer.valueOf(s));
            }
       }
       return stack.pop();
    }
}

滑动窗口最大值题目如下所示:

暴力求解不是我们做这道题的最优,这里引入单调队列进行求解:

根据栈与队列的知识,我们很容易能想到将滑动窗口的元素全部入队,每向右移动,队头元素就被pop,新push元素进队尾,然后在这个队列中找到最大值返回,这是最理想的解法,但实际情况并没有这种数据结构。在这个队列里的元素肯定是要进行排序的,最大值放在出口,但问题是移动时怎么弹出元素!!所以引申到我们没必要维护窗口里的所有元素,只要维护有可能成为窗口里最大值的元素就可以了,同时保证队列里的元素数值是由大到小的。那么这个维护元素单调递减的队列就叫做单调队列,即单调递减或单调递增的队列。

单调队列不是一成不变的,而是不同场景不同写法,总之要保证队列里单调递减或递增的原则,所以叫做单调队列。 不要以为本题中的单调队列实现就是固定的写法哈。

注意:deque是stack和queue默认的底层实现容器,deque是可以两边扩展的,而且deque里元素并不是严格的连续分布的。

自定义一个单调队列代码如下:

//自定义一个单调队列
class MyQueue{
    Deque<Integer> deque = new LinkedList<>();
    //重新定义入队和出队操作
    //1.弹出元素时,比较当前要弹出的数值是否等于队列出口的数值,如果相等则弹出
    void poll(int val){
        if(!deque.isEmpty() && val == deque.peek()){
            deque.poll();
        }
    }
    //2.添加元素时,如果要添加的元素大于入口元素,则将入口元素弹出
    //这样才能保证队列单调递减
    void add(int val){
        while(!deque.isEmpty() && val > deque.getLast()){
            deque.removeLast();
        }
        deque.add(val);
    }
    //3.队列的队顶元素始终为最大值
    int peek(){
        return deque.peek();
    }
}

最终实现的代码如下:

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        if(nums.length == 1){
            return nums;
        }
        int len = nums.length - k +1;//存放最大值的数组的长度
        int[] res = new int[len];
        int num = 0;
        MyQueue myQueue = new MyQueue();
        //1.首先将前k个元素放入队列
        for(int i = 0; i < k; i++){
            myQueue.add(nums[i]);
        }
        res[num++] = myQueue.peek();
        //2.开始滑动窗口
        for(int i = k; i < nums.length; i++){
            //2.1 滑动窗口移除最前面的元素
            myQueue.poll(nums[i-k]);
            //2.2 滑动窗口加入最后面的元素
            myQueue.add(nums[i]);
            //2.3 记录最大值
            res[num++] = myQueue.peek();
        }
        return res;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值