leetcode栈与队列刷题总结

一、理论

1. 栈

后进先出

//利用双端队列实现
Deque<> stack = new LinkedList<>();
//双端队列实现栈的常用方法
stack.push()
stack.pop()
stack.peek()
stack.isEmpty()

2. 队列

先进先出

Queue<> que = new LinkedList<>();
//个人习惯采用第一种
//成功返回true,失败时返回一个特殊值(取决于操作,为NULL或false)
que.offer();
que.poll();
que.peek();
//成功返回true,在操作失败时抛出异常
add(E e):添加一个元素到队尾
remove():获取队首的元素,并从队列中移除
element():获取队首的元素,但不从队列中移除
//
que.isEmpty();

3. 堆(优先级队列)

对于堆(使用PriorityQueue实现):从队头到队尾按从小到大排就是最小堆(小顶堆),
从队头到队尾按从大到小排就是最大堆(大顶堆)—>队头元素相当于堆的根节点

4. 单调栈

通常是一维数组,要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置,此时我们就要想到可以用单调栈了。
单调栈刷题总结

二、堆(优先队列)

1. 语法

  • 定义
    对于堆(使用PriorityQueue实现):从队头到队尾按从小到大排就是最小堆(小顶堆),
    从队头到队尾按从大到小排就是最大堆(大顶堆)—>队头元素相当于堆的根节点
  • 比较器
    PriorityQueue 默认是小根堆,大根堆需要重写比较器(一定要记住相关语法,哪个是大哪个小顶堆)。
    可以在 new PriorityQueue<>() 中的参数部分加入比较器。
    具体写法是:(v1, v2) -> v2 - v1。
    Queue 类的输入是 offer() 方法/add,弹出是 poll() 方法。

T347. 前k个高频元素 (大顶堆) **

在这里插入图片描述

  • 思路分析
    建立个大顶堆,频率次数高的元素在队头,优先出来(有一些题解强调要小顶堆 不理解!)
    小技巧:如何遍历一个map集合
    getOrDefault方法
  • 代码实现
class Solution {
    //优先队列实现大顶堆
    //getOrDefault() 方法获取指定 key 对应对 value,如果找不到 key ,则返回设置的默认值。
    public int[] topKFrequent(int[] nums, int k) {
        //1.计算值与出现频率
        Map<Integer,Integer> map = new HashMap<>();
        for(int i=0;i<nums.length;i++){
            map.put(nums[i],map.getOrDefault(nums[i],0)+1);
        }
        //2.创建大顶堆(从大到小),然后把map的值放到里面
        //大顶堆  [ [key,count], ... ]
        PriorityQueue<int[]> pq = new PriorityQueue<>( (x,y) -> y[1]-x[1]);
        //用map.entrySet 把map解析为 entry类型
        for(Map.Entry<Integer,Integer> entry:map.entrySet()){
            pq.add(new int[]{entry.getKey(),entry.getValue()});
        }
        //3.存放结果
        int[] res = new int[k];
        for(int i = 0;i<k;i++){
            res[i] = pq.poll()[0];
        }
        return res;
    }
}

面试题 17.14 最小K个数 (小顶堆) *

在这里插入图片描述

class Solution {
    //小顶堆
    public int[] smallestK(int[] arr, int k) {
        PriorityQueue<Integer> pq = new PriorityQueue<Integer>((x,y)->(x-y));//小顶堆
        for(int i=0;i<arr.length;i++){
            pq.offer(arr[i]);//队头到队尾:从小到大
        }
        int[] res = new int[k];
        for(int i=0;i<k;i++){
            res[i] = pq.poll();
        }
        return res;
    }
}

面试题 17.09. 第 k 个数

T692. 前k个高频单词

三、栈与队列相互转换

T232. 用栈实现队列

在这里插入图片描述

class MyQueue {
    Deque<Integer> stackIn;
    Deque<Integer> stackOut;
    public MyQueue() {
        stackIn = new LinkedList<Integer>();
        stackOut = new LinkedList<Integer>();
    }
    
    public void push(int x) {
        stackIn.push(x);
    }
    
    public int pop() {
        contrustOut();
        return stackOut.pop();
    }
    
    public int peek() {
        contrustOut();
        return stackOut.peek();
    }
    
    public boolean empty() {
        return stackIn.isEmpty() && stackOut.isEmpty();
    }
    public void contrustOut(){
        if(!stackOut.isEmpty()) return;
        while(!stackIn.isEmpty()){
            stackOut.push(stackIn.pop());
        }
    }
}

/**
 * Your MyQueue object will be instantiated and called as such:
 * MyQueue obj = new MyQueue();
 * obj.push(x);
 * int param_2 = obj.pop();
 * int param_3 = obj.peek();
 * boolean param_4 = obj.empty();
 */

T225. 队列实现栈

在这里插入图片描述
利用辅助队列来实现

class MyStack {
    //queue内置方法
    //offer添加元素
    //poll返回第一个元素,并删除
    //peek返回第一个元素
//核心做法:构造满足栈要求的队列,利用一个辅助队列来对元素排序后,放到目标队列里面去
//画图分析思路较为清晰
    Queue<Integer> que1;//用来模拟栈
    Queue<Integer> que2;//辅助队列
    public MyStack() {
        que1 = new LinkedList<>();
        que2 = new LinkedList<>();
    }
    
    public void push(int x) {
        que2.offer(x);
        while (!que1.isEmpty()){
            que2.offer(que1.poll());//新的队列,符合栈要求的队列
        }
        Queue<Integer> tempQue = que1;
        que1 = que2;//队列1为最终结果
        que2 = tempQue;//队列2为空队列
    }
    
    public int pop() {
        return que1.poll();
    }
    
    public int top() {
        return que1.peek();
    }
    
    public boolean empty() {
        return que1.isEmpty();
    }
}

/**
 * Your MyStack object will be instantiated and called as such:
 * MyStack obj = new MyStack();
 * obj.push(x);
 * int param_2 = obj.pop();
 * int param_3 = obj.top();
 * boolean param_4 = obj.empty();
 */

四、经典简单题

T20. 有效的括号(栈)

在这里插入图片描述

class Solution {
    public boolean isValid(String s) {
        Deque<Character> stack = new LinkedList<>();
        if(s.length()==1) return false;
        for(int i=0;i<s.length();i++){
            char ch = s.charAt(i);
            if(ch == ')'){
                if(stack.isEmpty() || stack.pop()!='(') return false;
            }
            else if(ch == ']'){
                if(stack.isEmpty() || stack.pop()!='[') return false;
            }
            else if(ch == '}'){
                if(stack.isEmpty() || stack.pop()!='{') return false;
            }else{
                stack.push(ch);
            }
        }
        return stack.isEmpty();
    }
}

T1047. 删除字符串中的所有重复字符(栈)

在这里插入图片描述

class Solution {
    public String removeDuplicates(String s) {
        Deque<Character> stack = new LinkedList<Character>();
        stack.push(s.charAt(0));
        for(int i=1;i<s.length();i++){
            if(stack.isEmpty() || s.charAt(i) != stack.peek()){
                stack.push(s.charAt(i));
            }else{
                stack.pop();
            }
        }
        String str = "";
        while(!stack.isEmpty()){
            str = stack.pop() + str;
        }
        return str;
    }
}

T150. 逆波兰表达式 **

在这里插入图片描述

class Solution {
    //遇到数字就入栈
    //遇到符号就弹出两个数字 进行处理后压入栈
    //Integer.valueOf  将基本类型int转换为包装类型Integer,或者将String转换成Integer
    public int evalRPN(String[] tokens) {
        Deque<Integer> stack = new LinkedList<Integer>();
        for(int i = 0;i<tokens.length;i++){
            String s = tokens[i];
            if( s.equals("+") ){// leetcode 内置jdk的问题,不能使用==判断字符串是否相等
                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("/")){
                int temp1 = stack.pop();
                int temp2 = stack.pop();
                stack.push(temp2/temp1);
            }else{
                stack.push(Integer.valueOf(s));
            }
        }
        return stack.pop();
    }
}

五、较为复杂的模拟题

1. 计算器系列问题

T224 基本计算器(没有乘除和空格,有 + - 括号)

在这里插入图片描述

  • 分析:
    用一个栈,记录数字和符号 顺序为数字、符号
    sign表示符号的正负
    遇到左括号 入栈 右括号 出栈
    如何把字符串变成数字
  • 代码实现
class Solution {
    //只有 加减括号
    //加减可以单独算,就用一个sign可以完成
    //遇到括号才入栈,依次是数字、符号
    //右括号就出栈,算出最终结果
    public int calculate(String s) {
        Deque<Integer> stack = new LinkedList<>();
        int sign = 1;//1代表正号 -1代表负号
        int len = s.length();
        int num = 0;
        for(int i=0;i<len;i++){
            char c = s.charAt(i);
            if(Character.isDigit(c)){
                int cur = c - '0';
                while(i+1<len && Character.isDigit(s.charAt(i+1))){
                    cur = cur * 10 + s.charAt(i+1) - '0';
                    i++;
                }
                num = num + sign * cur;//只要没遇到符号和括号 就把结果算出来
            }else if(c == '+'){
                sign = 1;
            }else if(c == '-'){
                sign = -1;
            }else if(c == '('){
                stack.push(num);
                num = 0;
                stack.push(sign);
                sign = 1;//先放数字后放符号
            }else if(c == ')'){
                num = stack.pop() * num + stack.pop();
            }
        }
        return num;
    }
}

T227. 基本计算器(加减乘除和空格,无括号)

在这里插入图片描述

T772

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值