算法day10 | Java | 栈和队列 | LeetCode 150,239,347(未完)

96 阅读2分钟

java

1、string

string转换为int
Integer.valueOf(s)

字符串对比 
s1.equals(s2)

2、优先队列

PriorityQueue

import java.util.PriorityQueue;
PriorityQueue<Integer> q1 = new PriorityQueue<>();

注意:默认情况下,PriorityQueue队列是小堆,如果需要大堆需要用户提供比较器


150. 逆波兰表达式求值

思路:借助栈,遇到数字压入栈,遇到操作符弹出栈顶两个元素进行操作并压入栈。

错误点:

①题目中给的逆波兰表达式是用 String[] tokens存储的。涉及到string转换为int:Integer.valueOf(s)

②本来想把 "+"(string)转换为 '+'(string),但不用这么干,本质是想对比是否相同,直接用字符串对比就可以。

③字符串对比 s1.equals(s2)

④如果操作符是减法或者除法,操作数的顺序 和 栈顶弹出元素 是相反的。

正确写法:

class Solution {
    public int evalRPN(String[] tokens) {
        Stack<Integer> stack = new Stack<>();
        //如果是数字,入栈
        //如果是符号,弹出栈顶两个元素运算,且还要把结果压回栈
        for(int i=0; i<tokens.length; i++) {
            String s = tokens[i];
            //string转换为int ? 不需要
            if(s.equals("+")) {
                stack.push(stack.pop()+stack.pop());
            } else if (s.equals("-")) {
                stack.push(-stack.pop()+stack.pop()); //错了
            } else if (s.equals("*")) {
                stack.push(stack.pop()*stack.pop());
            } else if (s.equals("/")) {
                // stack.push(stack.pop()/stack.pop()); //错了
                int tmp1 = stack.pop();
                int tmp2 = stack.pop();
                stack.push(tmp2/tmp1);
            } else {//数字
                // stack.push(s);
                stack.push(Integer.valueOf(s));
            }
        }
        return stack.pop();
    }
}

239. 滑动窗口最大值

单调队列

347.前 K 个高频元素

思路难点:①怎么求数组中每个元素的频率②怎么对频率进行排序

可以使用map元素,key存放元素,,value存放频率,对value进行排序,按快排的时间复杂度,nlogn

但我们没有必要对所有元素进行排序,只需要对k个进行排序。

【大顶堆、小顶堆】:适合在大数据集里,求k个高频、低频元素。堆底层实现是二叉树,大顶堆:根元素大于子元素数值。 时间复杂度:nlogk(n用堆遍历一遍数组,logk:在堆每加入一个元素)

优先级队列就是大顶堆和小顶堆。

class Solution {
    public int[] topKFrequent1(int[] nums, int k) {
        Map<Integer,Integer> map = new HashMap<>(); //key为数组元素值,val为对应出现次数
        for (int num : nums) {
            map.put(num, map.getOrDefault(num,0) + 1);
        }
        //在优先队列中存储二元组(num, cnt),cnt表示元素值num在数组中的出现次数
        //出现次数按从队头到队尾的顺序是从大到小排,出现次数最多的在队头(相当于大顶堆)
        PriorityQueue<int[]> pq = new PriorityQueue<>((pair1, pair2) -> pair2[1] - pair1[1]);
        for (Map.Entry<Integer, Integer> entry : map.entrySet()) {//大顶堆需要对所有元素进行排序
            pq.add(new int[]{entry.getKey(), entry.getValue()});
        }
        int[] ans = new int[k];
        for (int i = 0; i < k; i++) { //依次从队头弹出k个,就是出现频率前k高的元素
            ans[i] = pq.poll()[0];
        }
        return ans;
    }
}