• :

    • java.util.Stack:使用动态数组实现。

    • java.util.Deque:可以使用链表或动态数组实现。

  • 队列:

    • java.util.LinkedList:使用链表实现。

    • java.util.ArrayDeque:使用动态数组实现。

    • java.util.PriorityQueue:使用堆(数组实现的二叉堆)实现。

1、用栈实现队列

https://leetcode.cn/problems/implement-stack-using-queues/description/

两个栈即可。

class MyQueue {
    public Stack<Integer> in;
	public Stack<Integer> out;
    public MyQueue() {
		in = new Stack<Integer>();
		out = new Stack<Integer>();
    }
    public void inpushput(){
        if(out.empty()){
            while(!in.empty())
            out.push(in.pop());
        }
    }
    
    public void push(int x) {
        in.push(x);
        inpushput();

    }
    
    public int pop() {
        inpushput();
        return out.pop();

    }
    
    public int peek() {
        inpushput();
        return out.peek();


    }
    
    public boolean empty() {
    if(in.empty()&&out.empty())
    {
        return true;
    }
    return false;
    }
}

/**
 * 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();
 */

2、队列实现栈

https://leetcode.cn/problems/implement-stack-using-queues/description/

class MyStack {
    Queue<Integer> queue1;
    Queue<Integer> queue2;

    /** Initialize your data structure here. */
    public MyStack() {
        queue1 = new LinkedList<Integer>();
        queue2 = new LinkedList<Integer>();
    }
    
    /** Push element x onto stack. */
    public void push(int x) {
        queue2.offer(x);
        while (!queue1.isEmpty()) {
            queue2.offer(queue1.poll());
        }
        Queue<Integer> temp = queue1;
        queue1 = queue2;
        queue2 = temp;
    }
    
    /** Removes the element on top of the stack and returns that element. */
    public int pop() {
        return queue1.poll();
    }
    
    /** Get the top element. */
    public int top() {
        return queue1.peek();
    }
    
    /** Returns whether the stack is empty. */
    public boolean empty() {
        return queue1.isEmpty();
    }
}

3、有效的括号

https://leetcode.cn/problems/valid-parentheses/description/

class Solution {
    public boolean isValid(String s) {

 Stack<Character> stack = new Stack<>();
        int n=s.length();
        if(n%2!=0)
            return false;
        for(int i=0;i<n;i++){
            if(stack.size()>0){
                if(s.charAt(i)==')'){
                    if(stack.peek()=='(') {
                        stack.pop();
                        continue;
                    }
                }
                else if(s.charAt(i)==']'){
                    if(stack.peek()=='['){
                        stack.pop();
                       continue;}
                }
                else if(s.charAt(i)=='}'){
                    if(stack.peek()=='{'){
                        stack.pop();continue;}
                }
            }
            stack.push(s.charAt(i));
        }
        return stack.isEmpty();
    }
}

4、删除重复

①堆栈

class Solution {
   public  String removeDuplicates(String s) {
        Stack<Character> stack = new Stack<>();
        for(int i=0;i<s.length();i++){
            if(stack.size()>0){
                if(s.charAt(i)==stack.peek()){
                    stack.pop();
                    continue;
                }
            }
            stack.push(s.charAt(i));
        }
        StringBuilder sb=new StringBuilder();
        int size = stack.size();
        for(int i=0;i<size;i++){
            sb.append(stack.peek());
            stack.pop();
        }
        sb.reverse();
        return sb.toString();}
}

②用StringBuilder来代替堆栈

class Solution {
   public  String removeDuplicates(String s) {
      StringBuilder stringBuilder=new StringBuilder();
        int count=-1;
        for(int i=0;i<s.length();i++){
            if(count>=0&& stringBuilder.charAt(count)==s.charAt(i)){
                stringBuilder.deleteCharAt(count--);
            }
            else {
                stringBuilder.append(s.charAt(i));
                count++;
            }
        }
        return stringBuilder.toString();
   }
}

③双指针

class Solution {
   public  String removeDuplicates(String s) {
     char[] c = s.toCharArray();
        int slow=0;
       int fast=0;
        for (int i = 0; i <s.length() ; i++) {
            c[slow]=c[fast];
            if(slow>0&&c[slow]==c[slow-1]){
                slow--;
            }
            else {
                slow++;
            }
            fast++;
        }
        return new String(c,0,slow);
   }
}

5、逆波兰表达式

https://leetcode.cn/problems/evaluate-reverse-polish-notation/description/

注意字符串要用equals进行对比,用==进行比较的是内存地址,而不是具体的值

Integer.valueOf  把 字符串转为int类型。

class Solution {
    public int evalRPN(String[] tokens) {
        int n = tokens.length;
        Stack<Integer> stack = new Stack<>();
        
        for (int i = 0; i < n; i++) {
            if (tokens[i].equals("+") || tokens[i].equals("-")
                || tokens[i].equals("*") || tokens[i].equals("/")) {
                
                int s2 = stack.pop(); // 从栈中弹出第一个操作数
                int s1 = stack.pop(); // 从栈中弹出第二个操作数
                
                if (tokens[i].equals("+"))
                    stack.push(s1 + s2);
                if (tokens[i].equals("-"))
                    stack.push(s1 - s2);
                if (tokens[i].equals("*"))
                    stack.push(s1 * s2);
                if (tokens[i].equals("/"))
                    stack.push(s1 / s2);
                
            } else {
                stack.push(Integer.parseInt(tokens[i])); // 将数字压入栈中
            }
        }
        
        return stack.pop(); // 返回最后栈中的结果
    }
}
class Solution {
    public int evalRPN(String[] tokens) {
        Deque<Integer> stack = new LinkedList();
        for (String s : tokens) {
            if ("+".equals(s)) {        // leetcode 内置jdk的问题,不能使用==判断字符串是否相等
                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();
    }
}

6、前k个高频元素

优先级队列 大顶堆小顶堆

https://leetcode.cn/problems/top-k-frequent-elements/description/

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
    
    //遍历数组,存放num 和其对应的次数
   Map<Integer,Integer> map=new HashMap<>();
        for (int num : nums) {
            map.put(num, map.getOrDefault(num,0)+1);
        }
        //小顶堆 
        PriorityQueue<int[]> pq=new PriorityQueue<>((pair1,pair2)->(pair1[1]-pair2[1]));
        //遍历map 维护大小为k的小顶堆 
        for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
            if(pq.size()<k)
                pq.add(new int[]{entry.getKey(),entry.getValue()});
            else{
                //只有cnt大于当前小顶堆的栈顶时 才添加
                if(entry.getValue()> pq.peek()[1]){
                    pq.poll();
                    pq.add(new int[]{entry.getKey(),entry.getValue()});
                }
            }
        }
        int[] res=new int[k];
        for(int i=0;i<k;i++){
            res[i]=pq.poll()[0];
        }
        return res;
    }
}

7.滑动窗口最大值

单调队列

https://leetcode.cn/problems/sliding-window-maximum/description/

class MyQueue {
    Deque<Integer> deque = new LinkedList<>();
    //弹出元素时,比较当前要弹出的数值是否等于队列出口的数值,如果相等则弹出
    //同时判断队列当前是否为空
    void poll(int val) {
        if (!deque.isEmpty() && val == deque.peek()) {
            deque.poll();
        }
    }
    //添加元素时,如果要添加的元素大于入口处的元素,就将入口元素弹出
    //保证队列元素单调递减
    //比如此时队列元素3,1,2将要入队,比1大,所以1弹出,此时队列:3,2
    void add(int val) {
        while (!deque.isEmpty() && val > deque.getLast()) {
            deque.removeLast();
        }
        deque.add(val);
    }
    //队列队顶元素始终为最大值
    int peek() {
        return deque.peek();
    }
}

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        if (nums.length == 1) {
            return nums;
        }
        int len = nums.length - k + 1;
        //存放结果元素的数组
        int[] res = new int[len];
        int num = 0;
        //自定义队列
        MyQueue myQueue = new MyQueue();
        //先将前k的元素放入队列
        for (int i = 0; i < k; i++) {
            myQueue.add(nums[i]);
        }
        res[num++] = myQueue.peek();
        for (int i = k; i < nums.length; i++) {
            //滑动窗口移除最前面的元素,移除是判断该元素是否放入队列
            myQueue.poll(nums[i - k]);
            //滑动窗口加入最后面的元素
            myQueue.add(nums[i]);
            //记录对应的最大值
            res[num++] = myQueue.peek();
        }
        return res;
    }
}