Day10 | 150. 逆波兰表达式求值 239. 滑动窗口最大值 347.前 K 个高频元素

语言

Java

150. 逆波兰表达式求值

题目连接:逆波兰表达式求值

题目

给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。

请你计算该表达式。返回一个表示表达式值的整数。

思路

我们采用栈这个数据结构来解决这个问题,我们先遍历数组,将他的元素放到栈中,如果碰到‘+’就相加’-‘就相减’*‘就相乘’/‘就相除,最后一个栈中的数就是我们要返回的值。

具体细节看代码

代码

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();
    }
}

易错点

注意栈是先进后出的,比较’-‘号的时候要第一个是被减的

还有’/‘号的时候也是。

时间复杂度

时间复杂度: O(n)
空间复杂度: O(n)

239. 滑动窗口最大值

题目连接:滑动窗口最大值

题目

给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。

返回 滑动窗口中的最大值 

思路

先创建一个双端队列,定义一个结果数组,先循环遍历源数组,判断如果是空或者不符合范围要弹出,判断如果没有末尾的数大也要弹出,再加入新的元素到队列中,每K个将最大的数添加到结果数组中。具体细节看代码

代码

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        ArrayDeque<Integer> deque = new ArrayDeque<>();//定义双端队列
        int n = nums.length;//数组长度
        int[] res = new int[n - k + 1];//定义结果数组大小
        int idx = 0;//用来存放结果的索引
        for (int i = 0; i < n; i++) {//遍历数组
            while (!deque.isEmpty() && deque.peek() < i - k + 1) {//不符合范围的都弹出
                deque.poll();
            }
            while (!deque.isEmpty() && nums[deque.peekLast()] < nums[i]) {//比末尾小的也弹出
                deque.pollLast();
            }
            deque.offer(i);//加入遍历的元素
            if (i >= k - 1) {//获得最大值
                res[idx++] = nums[deque.peek()];
            }
        }
        return res;
    }
}

易错点

1.忘记判断不在数组范围的情况了

2.容易忘记不大于队尾的元素也要弹出。

思路是最重要的

时间复杂度

时间复杂度: O(n)
空间复杂度: O(k)

347.前 K 个高频元素

题目链接:前 K 个高频元素

题目

给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。

思路

先用Map存元素和元素出现的次数,然后用队列和小顶堆的数据结构进行解决。具体过程是

循环遍历数组存在Map中,创建优先队列,再遍历map。判断队列中的元素是否小于k,小于的话直接把map中的元素添加到队列中,如果没有小于,进行对比,如果新元素大,弹出队头,加入新元素。

最后把一整个小顶堆上的元素全弹出,先弹出的是最少的,后弹出的是大的,从大到小加入到结果数组中,返回结果数组。具体细节看代码。

代码

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        Map<Integer,Integer> map = new HashMap<>();//map用来存出现的元素和出现次数.
        for (int num : nums) {
            map.put(num, map.getOrDefault(num, 0) + 1);//key元素value次数。
        }
        //创建一个优先级队列,并且保证是升序排列的
        PriorityQueue<int[]> pq = new PriorityQueue<>((pair1, pair2) -> pair1[1] - pair2[1]);
        for (Map.Entry<Integer,Integer> entry : map.entrySet()) {//遍历map,采用小顶堆的数据结构
            if (pq.size() < k ) {//队列元素小于k直接添加
                pq.add(new int[]{entry.getKey(), entry.getValue()});
            } else {
                if (entry.getValue() > pq.peek()[1]) {//如果VALUE值大于队列中的
                    pq.poll();//弹出队头,即小顶堆的根节点,就是最少的弹出了,留下的是出现次数多的了
                    pq.add(new int[]{entry.getKey(), entry.getValue()});//加入出现次数多的
                }
            }
        }
        int[] res = new int[k];//定义一个结果数组
        for (int i = k - 1; i >= 0; i--) {//依次弹出小顶堆
            res[i] = pq.poll()[0];//先弹出的是根也就是出现次数少的,后面是弹出的多的
        }
        return res;//例题中也展示的是出现元素最多的放前面
    }
}

易错点

弹出队首和队尾的时候要小心一些。

基本队列方法不要写错。

时间复杂度

  • 时间复杂度: O(nlogk)
  • 空间复杂度: O(n)

总结

栈和队列今天就算完结了,今天我体会到了写注释的重要性,以后的代码我会多多写注释,来保证思路的完整性。

继续加油!我亦无他唯手熟而。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值