代码随想录第十三天 | 150. 逆波兰表达式求值、239. 滑动窗口最大值、347.前 K 个高频元素
第一题150. 逆波兰表达式求值
根据 逆波兰表示法,求表达式的值。
有效的算符包括 +、-、*、/ 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。
注意 两个整数之间的除法只保留整数部分。
可以保证给定的逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。
ψ(`∇´)ψ 我的思路
- 题目上提示的已经很清晰了
去掉括号后表达式无歧义,上式即便写成 1 2 + 3 4 + * 也可以依据次序计算出正确结果。
适合用栈操作运算:遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中
package stackandqueue;
import java.util.Stack;
public class EvalRPN {
public int evalRPN(String[] tokens) {
int m,n;
Stack<String> stack = new Stack<>();
for (int i = 0; i < tokens.length; i++) {
//如果是运算符的话,取出栈顶的两个元素,和运算符计算,结果入栈
if(tokens[i].equals("+")){
stack.push(String.valueOf(Integer.parseInt(stack.pop())+Integer.parseInt(stack.pop())));
} else if (tokens[i].equals("-")) {
m = Integer.parseInt(stack.pop());
n = Integer.parseInt(stack.pop());
stack.push(String.valueOf(n-m));
} else if (tokens[i].equals("*")) {
stack.push(String.valueOf(Integer.parseInt(stack.pop())*Integer.parseInt(stack.pop())));
}else if (tokens[i].equals("/")) {
m = Integer.parseInt(stack.pop());
n = Integer.parseInt(stack.pop());
stack.push(String.valueOf(n/m));
} else {
stack.push(tokens[i]);//如果不是运算符的话,入栈
}
}
return Integer.parseInt(stack.pop());
}
}
时间复杂度O(n)
- 在力扣上debug也太方便了吧
第二题239. 滑动窗口最大值
给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值

ψ(`∇´)ψ 我的思路
- 暴力暴力!一个for循环确定滑动窗口的位置,另一个for循环确定滑动窗口内的最大值
package stackandqueue;
public class MaxSlidingWindow {
public int[] maxSlidingWindow(int[] nums, int k) {
if (nums.length==1){
return nums;
}
int[] res = new int[nums.length - k + 1];//结果数组
for (int i = 0; i < nums.length - k + 1; i++) {
// 确定滑动窗口的位置[i,i+k-1]
int x = Integer.MIN_VALUE;
for (int j = i; j < i + k; j++) {
// 遍历滑动窗口内的值,寻找最大值
x = nums[j] > x ? nums[j] : x;
}
res[i] = x;
}
return res;
}
}
时间复杂度O(n^2)
- 然后就。。。超时了

- 就很乖的去看了正经解法

package stackandqueue;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.LinkedList;
public class MaxSlidingWindow2 {
static Deque<Integer> que = new LinkedList<>();
public static int[] maxSlidingWindow(int[] nums, int k) {
int[] res = new int[nums.length - k + 1];
for (int i = 0; i < k; i++) {
push(nums[i]);
}
res[0] = getMax();
for (int i = 1; i < nums.length - k + 1; i++) {
pop(nums[i-1]);//弹出元素
push(nums[i + k-1]);//加入元素
res[i] = getMax();//取最大值
}
return res;
}
public static void pop(int x) {
if (!que.isEmpty() && que.peek() == x) {
//如果队列不为空,并且队列出口的值=要弹出的值
que.pop();
}
}
public static void push(int x) {
while (!que.isEmpty()&&x>que.getLast()){
que.removeLast();//当队列不空且要加入的元素大于队列最后一个元素时,把最后的元素去掉(保证队列倒序)
}
que.addLast(x);//在把元素追加至队尾
}
public static int getMax() {
// 最大值一直是队列出口的元素
return (int) que.getFirst();
}
public static void main(String[] args) {
int[] ints = maxSlidingWindow(new int[]{1,3,1,2,0,5}, 3);
for (int i = 0; i < ints.length; i++) {
System.out.println(ints[i]);
}
}
}
时间复杂度O(n)
- 尽管听了思路,实现起来还是有点复杂的,关键是push的时候要从队尾把元素移除,再加入元素,这样可以保证队列里的元素倒序。
第三题347.前 K 个高频元素
给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
ψ(`∇´)ψ 我的思路
- 这题我想着是用map,出现的次数为key,出现的元素为value,for循环一次遍历将数组存入map,对key排序,取前k个返回其value。今天不太舒服就不写了,直接看代码随想录的新方法。
package stackandqueue;
import java.util.HashMap;
import java.util.Map;
import java.util.PriorityQueue;
public class TopKFrequent {
public int[] topKFrequent(int[] nums, int k) {
// 先把数组中的元素装入map
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
if (!map.containsKey(nums[i])) {
map.put(nums[i], 1);
} else {
map.put(nums[i],map.get(nums[i])+1);
}
}
PriorityQueue<int[]> pq = new PriorityQueue<>((pair1, pair2)->pair1[1]-pair2[1]);
for(Map.Entry<Integer,Integer> entry:map.entrySet()){//小顶堆只需要维持k个元素有序
if(pq.size()<k){//小顶堆元素个数小于k个时直接加
pq.add(new int[]{entry.getKey(),entry.getValue()});
}else{
if(entry.getValue()>pq.peek()[1]){//当前元素出现次数大于小顶堆的根结点(这k个元素中出现次数最少的那个)
pq.poll();//弹出队头(小顶堆的根结点),即把堆里出现次数最少的那个删除,留下的就是出现次数多的了
pq.add(new int[]{entry.getKey(),entry.getValue()});
}
}
}
int[] ans = new int[k];
for(int i=k-1;i>=0;i--){//依次弹出小顶堆,先弹出的是堆的根,出现次数少,后面弹出的出现次数多
ans[i] = pq.poll()[0];
}
return ans;
}
}
- 思路听了下,但并不是很理解PriorityQueue这个东西,感觉我对队列的理解还是差点儿
总结
- 基本可以用栈来解题,但是队列我还是没有完全弄明白,大顶堆小顶堆也只是懂一点儿,先欠下来,等6号,7号的时候再做个总结。
- 今天终于做到了一道困难题,还是很开心的,期待二叉树
补充
队列

- 实现类挺多的,一般用LinkedList
堆
- 堆是一个完全二叉树
- 大顶堆:头部为堆中最大的值
- 小顶堆:头部为队中最小的值
- PriorityQueue:一个具有优先级的队列,该优先级使得队列始终按照自然顺序进行排序,队列的头部为最小值。

构造小顶堆:
PriorityQueue small=new PriorityQueue<>();
构造大顶堆:
PriorityQueue small=new PriorityQueue<>(Collections.reverseOrder());
代码随想录第十三天 | 150. 逆波兰表达式求值、239. 滑动窗口最大值、347.前 K 个高频元素的更多相关文章
- LeetCode 150. 逆波兰表达式求值(Evaluate Reverse Polish Notation) 24
150. 逆波兰表达式求值 150. Evaluate Reverse Polish Notation 题目描述 根据逆波兰表示法,求表达式的值. 有效的运算符包括 +, -, *, /.每个运算对象 ...
- Java实现 LeetCode 150 逆波兰表达式求值
150. 逆波兰表达式求值 根据逆波兰表示法,求表达式的值. 有效的运算符包括 +, -, *, / .每个运算对象可以是整数,也可以是另一个逆波兰表达式. 说明: 整数除法只保留整数部分. 给定逆波 ...
- Leetcode 150.逆波兰表达式求值
逆波兰表达式求值 根据逆波兰表示法,求表达式的值. 有效的运算符包括 +, -, *, / .每个运算对象可以是整数,也可以是另一个逆波兰表达式. 说明: 整数除法只保留整数部分. 给定逆波兰表达式总 ...
- LeetCode:逆波兰表达式求值【150】
LeetCode:逆波兰表达式求值[150] 题目描述 根据逆波兰表示法,求表达式的值. 有效的运算符包括 +, -, *, / .每个运算对象可以是整数,也可以是另一个逆波兰表达式. 说明: 整数除 ...
- 【python】Leetcode每日一题-逆波兰表达式求值
[python]Leetcode每日一题-逆波兰表达式求值 [题目描述] 根据 逆波兰表示法,求表达式的值. 有效的算符包括 +.-.*./ .每个运算对象可以是整数,也可以是另一个逆波兰表达式. 说 ...
- lintcode 中等题:Evaluate Reverse Polish notation逆波兰表达式求值
题目 逆波兰表达式求值 在逆波兰表达法中,其有效的运算符号包括 +, -, *, / .每个运算对象可以是整数,也可以是另一个逆波兰计数表达. 样例 ["2", "1&q ...
- SDIBT2666——逆波兰表达式求值
逆波兰表达式求值(栈和队列) Description 从键盘上输入一个逆波兰表达式,用伪码写出其求值程序.规定:逆波兰表达式的长度不超过一行,以@符作为输入结束,操作数之间用空格分隔,操作符只可能有+ ...
- CH BR4思考熊(恒等有理式-逆波兰表达式求值)
恒等有理式 总时限 10s 内存限制 256MB 出题人 fotile96 提交情况 4/43 描述 给定两个有理式f(X)与g(X),判断他们是否恒等(任意A,如果f(A)与g(A)均有定义,那么f ...
- leetcode算法学习----逆波兰表达式求值(后缀表达式)
下面题目是LeetCode算法:逆波兰表达式求值(java实现) 逆波兰表达式即后缀表达式. 题目: 有效的运算符包括 +, -, *, / .每个运算对象可以是整数,也可以是另一个逆波兰表达式.同 ...
随机推荐
- DP の 百题大过关(5/100)
动态规划自古以来是DALAO凌虐萌新的分水岭,但有些OIer认为并没有这么重要--会打暴力,大不了记忆化.但是其实,动态规划学得好不好,可以彰显出一个OIerOIer的基本素养--能否富有逻辑地思 ...
- Vue3.0工程创建 && setup、ref、reactive函数 && Vue3.0响应式实现原理
1 # 一.创建Vue3.0工程 2 # 1.使用vue-cli创建 3 # 官方文档: https://cli.vuejs.org/zh/guide/creating-a-project.html# ...
- Maven 聚合工程
第一步: 创建Maven聚合工程: 父工程Maven工程的打包方式必须为pom 创建一个Maven工程 修改父工程的pom.xml,设置打包方式为pom <?xml version=" ...
- 感谢有你!Apache DolphinScheduler 项目 GitHub star 突破 8k
本周伊始,Apache DolphinScheduler 项目在 GitHub 上的 Github Star 总数首次突破 8K.目前,Apache DolphinScheduler 社区已经拥有 C ...
- JDK数组阻塞队列源码深入剖析
JDK数组阻塞队列源码深入剖析 前言 在前面一篇文章从零开始自己动手写阻塞队列当中我们仔细介绍了阻塞队列提供给我们的功能,以及他的实现原理,并且基于谈到的内容我们自己实现了一个低配版的数组阻塞队列.在 ...
- 初次认识 Canvas
画布的概念 Canvas(画布)可以用于动画.游戏画面.数据可视化.图片编辑以及实时视频处理等方面.画布在 HTML5 中是通过canvas标签来表现,通过 JavaScript 提供的画布 API, ...
- 46th ECfinal 游记
Day0 坐高铁坐了七小时从北戴河到西安,但第一次线下赛,来的路上还是很激动的 路上看到华山,下次来西安一定去爬 刚下高铁站遇到了一个不知道干啥的xjj xjj:可以占用您一点时间吗?谢谢了. 我:不 ...
- 中国剩余定理+扩展中国剩余定理 讲解+例题(HDU1370 Biorhythms + POJ2891 Strange Way to Express Integers)
0.引子 每一个讲中国剩余定理的人,都会从孙子的一道例题讲起 有物不知其数,三三数之剩二,五五数之剩三,七七数之剩二.问物几何? 1.中国剩余定理 引子里的例题实际上是求一个最小的x满足 关键是,其中 ...
- 【JDBC】学习路径7-转账-commit事务操作
现在我们要做一个转账系统. 第一章:创建一张新的表格(用户银行账户表格) 在之前的JDBC_01数据库中新增一个表格,名字为:Account 其中,有id.银行卡号.银行密码.账户余额. 创建表格 ...
- 【Java】学习路径34-文件IO练习题
练习题: 1.检测某目录(scr目录为例)下java源程序文件的数量. 参考思路: 首先获取到scr目录,然后使用list()获取所有名字,再使用String类下的endsWith方法检查即可. 参考 ...