代码随想录第十三天 | 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实现) 逆波兰表达式即后缀表达式. 题目: 有效的运算符包括 +, -, *, / .每个运算对象可以是整数,也可以是另一个逆波兰表达式.同 ...
随机推荐
- netcore 非注入全局获取配置文件
在netcore开发中,最常见的就是注入,比如想获取appsettings.json的内容,我们就需要去注入,然后在controller里面去获取,但是我们如果想要在service中使用appsett ...
- 精心总结十三条建议,帮你创建更合适的MySQL索引
上篇文章讲到使用MySQL的Explain命令可以分析SQL性能瓶颈,优化SQL查询,以及查看是否用到了索引. 我们都知道创建索引可以提高查询效率,但是具体该怎么创建索引? 哪些字段适合创建索引? 哪 ...
- 高考集训讲课(To 高一)
高考集训讲课(To 高一) 主要是怕下午讲着讲着把自己讲懵了,有一定的迷糊概率 经过机房的讨论,一致认为插头\(DP\)实用性不大,所以这次不讲了,先把重要的讲一讲. 顺便吐槽一下,凭什么另外几个人都 ...
- SQL Server查询优化
从上至下优化 看过一篇文章,印象深刻,里面将数据库查询优化分为四个大的方向 使用钞能力--给DB服务器加物理配置,内存啊,CPU啊,硬盘啊,全上顶配 替换存储系统--根据实际的业务情况选择不同的存储数 ...
- Eclipse里项目名有红叉,但是项目里的每一个文件都没有红叉
原因一:导入的文件被删除了. 解决方法:右击项目名,在弹出的菜单中,选择"Bulid Path"-->"configure build path"--&g ...
- Apache DolphinScheduler 是如何诞生的
作者 | 代立冬,李岗 排版 | 开源之道小助理 Apache DolphinScheduler,简称"DS", 中文名 "小海豚调度"(海豚聪明.人性化,又左 ...
- MySQL 数据查询语句
一般查询 字段取别名 别名不用加单引号,as 可省略. select t.id ID, t.name 名称 from grade t; 拼接字符串 concat(a, b) select concat ...
- Canvas 线性图形(一):路径
路径的概念 路径是从起始点到结束点之间的连线.个人认为,二维画布中分为线性图形和非线性图形,线性图形包括矩形.直线.曲线.圆形等各种几何图形:非线性图形包括图象.文本.像素.线性图形中又分为路径和非路 ...
- 解决:Uncaught TypeError: $ is not a function
本来好好的,突然就出现的错误,不过这并不是什么难解决的错误: 我的问题是:在js文件里我定义了一个var $;变量,只要把这个去掉就没问题了. 出现这种错误的解决方法: 1,先看看你的jq文件是否已经 ...
- Atcoder Beginner Contest 200 E. Minflip Summation(概率数论)
题面 一个字符串 T T T 是由一个包含 0.1.? 的字符串 S S S 循环连接 K K K 次获得的. 字符串 T T T 中的每个 ? 都可以换成 0 或 1 ,假设 T T T 中一共有 ...