代码随想录算法训练营第九天/150.逆波兰表达式求值、239.滑动窗口最大值、347.前k个高频元素

目录

今日内容:

150.逆波兰表达式

239.滑动窗口最大值

347.前k个高频元素


150.逆波兰表达式求值

题目链接:https://leetcode.cn/problems/evaluate-reverse-polish-notation/submissions/

题目了解:首先了解逆波兰表达式的概念,按照题目:给出一个String数组,里面包含数字和逆波兰表达式中的几个符号;要理解是按照什么顺序进行运算的才能完成此题,所以要先看示例知道顺序。

示例 1:

输入:tokens = ["2","1","+","3","*"]
输出:9
解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9


示例 2:

输入:tokens = ["4","13","5","/","+"]
输出:6
解释:该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6


示例 3:

输入:tokens = ["10","6","9","3","+","-11","*","/","*","17","+","5","+"]
输出:22
解释:该算式转化为常见的中缀算术表达式为:
  ((10 * (6 / ((9 + 3) * -11))) + 17) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= ((10 * 0) + 17) + 5
= (0 + 17) + 5
= 17 + 5
= 22

思路

此题有点类似于“消除全部相邻重复项”,只是那题是消除而本题是对这些相邻元素进行运算;本题需要用到一个栈用来存放遍历数组中的元素and相邻元素进行运算后的结果;先对数组进行遍历,若是数字或者栈为空时就push入栈中;如果是运算符,那么需要分类判断,这里的前提是栈不为空,然后用多个else if判断:当为“+”时,则需要将获得栈中的连续pop出的两个数运算,然后再将这两数运算结果push入栈中,继续遍历下一个;当遍历到每个运算符都是按照这步骤,但是需要注意到的是:进行运算时是当前栈顶的前一个数去“+”、“-”、“*”、“/”栈顶的数,要按照这个顺序,所以“-”和“/”就需要非常注意这个顺序了,除数被除数减数被减数千万不要弄反。

class Solution {
    public int evalRPN(String[] tokens) {
        Stack<Integer> stack=new Stack<Integer>();//栈存放遍历和运算后获得的整数值
        for(String s:tokens){
            if(s.equals("+")){
                stack.push(stack.pop()+stack.pop());
            }else if(s.equals("-")){
               int temp1=stack.pop();
               int temp2=stack.pop();
               stack.push(temp2-temp1);
            }else if(s.equals("*")){
                stack.push(stack.pop()*stack.pop());
            }else if(s.equals("/")){
                int temp1=stack.pop();
                int temp2=stack.pop();
                stack.push(temp2/temp1);
            }else{
                stack.push(Integer.parseInt(s));
            }
        }
            return stack.pop();
    }
}


239.滑动窗口最大值

https://leetcode.cn/problems/sliding-window-maximum/

思路

本题用到:双端队列,概念:在队头和队尾均可以进行插入删除;本题会用到双端队列来存放原整数数组中元素对应的索引下标。

此题需要先明确几个点,就是完成此题的步骤:

1.最后需要返回每个窗口获得最大值的数组,那么此数组的长度是?

解答:新数组的长度应为(n为原数组长度,k为每个窗口长度):n-k+1

2.每次新窗口的位置范围是什么?

解答:窗口是不断变化但是长度不变的,所以范围一直都在改变,范围是(i是当前遍历到的索引):[i-k+1,i];因为队列存放的就是索引值,所以当队头元素不在此范围内也就是小于此范围最小数,那么就需要将此队头poll出来。

3.如何进行比较得到最大数?

解答:这是关键一步:每次遍历到的“索引元素对应值”和“队尾索引对应值”进行比较,若前者大,则需要将后者pollLast()出队列,这个比较是一直进行的,当不满足这个条件时才跳出循环。

4.在什么时候取得最大值入数组中?

解答:当i遍历到:i>=k-1时,就开始取队列中队头索引对应值进入数组中。

整体过程

以上几个问题是完成此题需要知道的点,首先创建一个按规律得长度为:n-k+1的新数组;接着队原数组进行遍历,这里要设置几个条件:(1)、当队列不为空时,对头第一个索引不在上述范围内,那需要将此对头索引poll()出队列;(2)当队列不为空时,比较当前i对应数值同队尾索引对应数值,前者大的话就要将当前队尾pollLast()出队列,一直循环此操作,直到不满足条件时跳出循环;所以以上两个需要用while来判断。在满足结束了这两个循环后,使用offer(int x)将当前索引i加入到队列中,接下来就是获得每个窗口最大值,按照判断条件:i>=k-1,就获得队头进入新数组,按以上操作每次获得的队头都是最大值,然后一直重复以上过程不断获得新窗口,最后返回新数组。

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        Deque<Integer> deque=new LinkedList<Integer>();
        int n=nums.length;
        int j=0;
        //设置数组存放新窗口每次的最大值
        int [] result=new int[n-k+1];
        //队列里存放的是数组里元素的下标
        for(int i=0;i<nums.length;i++){
            //每次新窗口的范围应在[i-k+1,i]
            while(!deque.isEmpty()&&deque.peek()<i-k+1){
                deque.poll();
            }
            while(!deque.isEmpty()&&nums[i]>nums[deque.peekLast()]){
                deque.pollLast();
            }
            deque.offer(i);
            if(i>=k-1){
            result[j++]=nums[deque.peek()];
        }
        }
        return result;
    }
}


(后续)347.前k个高频元素

1.利用map集合来统计各数的频率

2.?利用大堆栈或者小堆栈(这个不理解)

此题暂时未理解完毕,等此次全部刷题结束将未完成的题目拉出来单独学习!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值