LeetCode Brushing Questions: Stacks and Queues

Stack

Implement stack with 2 queues

https://leetcode-cn.com/problems/implement-stack-using-queues/
Insert picture description here

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()) {
    
    
            // 核心就是让后入变成先入,最后操作的在offer处插队成为首个,过去插队维护的再输入进来即可
            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();
    }
}

439. Ternary Expression Parser

https://leetcode-cn.com/problems/ternary-expression-parser/
Insert picture description here

Key point:

  1. Character.isDigit judges the number
  2. What is the mark of judgment processing (stacking and popping)? And whoever goes to the stack and who goes out of the stack afterwards, the last thing left is the answer.
    Only one traversal is required.
    Insert picture description here

71. Simplify the path

Insert picture description here

class Solution {
    
    
    public String simplifyPath(String path) {
    
    
        String[] strings = path.split("/");
        Stack<String> stack = new Stack<>();
        for(String str : strings) {
    
    
            if(str.isEmpty() || str.equalsIgnoreCase(".") || str.equalsIgnoreCase("/")) {
    
    
                continue;
            }
            if(str.equalsIgnoreCase("..")) {
    
    
                if(!stack.isEmpty()) {
    
    
                    stack.pop();
                }
                continue;
            }
            stack.push(str);
        }
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("/");
        for(String str : stack) {
    
    
            stringBuilder.append(str);
            stringBuilder.append("/");
        }
        if(stringBuilder.toString().length() == 1) {
    
    
            return stringBuilder.toString();
        }
        return stringBuilder.toString().substring(0, stringBuilder.length() - 1);
    }
}

316. Remove duplicate letters

Insert picture description here

Essentials:
Greedy + stack

  1. Stored in the stack are the current optimal solutions verified by the greedy algorithm.
    Each time it is necessary to determine whether the characters to be processed should be added and whether the previous repeated characters can be replaced
class Solution {
    
    
    private int[] letterNum = new int[26];
    public String removeDuplicateLetters(String s) {
    
    
        if (s == null || s.isEmpty() || s.length() == 1) {
    
    
            return s;
        }
        initArray(s);
        Stack<Character> stack = new Stack<>();
        for (int i = 0; i < s.length(); i++) {
    
    
            char sTmp = s.charAt(i);
            letterNum[sTmp - 'a']--;
            if(stack.isEmpty()) {
    
    
                stack.push(sTmp);
                continue;
            }
            while (!stack.isEmpty()) {
    
    
// 判断当前字符与stack已经入栈字符之间的关系
                char stackTmp = stack.peek();
// 已经入栈的字符无需处理
                if(stack.contains(sTmp)) {
    
    
                    break;
                }
                if(stackTmp - sTmp >= 0 && !isLastOne(stackTmp)) {
    
    
// 之前入栈的每个字符需要经过新字符的洗练。需要在后续有重复的基础上满足字典序最小
                    stack.pop();
                } else {
    
    
// 遇到第一个无法处理的立即终止
                    break;
                }
            }
            if (!stack.contains(sTmp)) {
    
    
 // 栈中补充上该字符
                stack.push(sTmp);
            }
        }
        StringBuilder stringBuilder = new StringBuilder();
        for(Character c :stack) {
    
    
            stringBuilder.append(c);
        }
        return stringBuilder.toString();
    }
    private void initArray(String s) {
    
    
        for (Character c : s.toCharArray()) {
    
    
            letterNum[c - 'a']++;
        }
    }
    private boolean isLastOne(char c) {
    
    
   // 判断是否是最后一个
        return letterNum[c - 'a'] == 0;
    }
}

queue

Core points:

  1. Three subscripts: size, first, last.
    Think about the actual meaning of first and last:
    the relationship between the subscript representing the exact existing element and not the next first at the position is: only one situation will overlap. When there is only one element in the array.
class MyCircularQueue {
    
    
    Object[] queue = null;
        int first = 0;
        int last = 0;
        int size = 0;
        public MyCircularQueue(int k) {
    
    
            queue = new Object[k];
            first = 0;
            last = 0;
            size = k;
        }
        public boolean enQueue(int value) {
    
    
            if (last + 1 == first || (last + 1 == size && first == 0)) {
    
    
                return false;
            }
            if(last == first && queue[last] == null) {
    
    
                queue[last] = value;
                return true;
            }
            last++;
            if (last == size) {
    
    
                last = 0;
            }
            queue[last] = value;
            return true;
        }
        public boolean deQueue() {
    
    
            if (last == first) {
    
    
                if(queue[first] == null) {
    
    
                    return false;
                } else {
    
    
                    queue[first] = null;
                    return true;
                }
            }
            queue[first] = null;
            first ++;
            if (first == size) {
    
    
                first = 0;
            }
            return true;
        }
        public int Front() {
    
    
            if (queue[first] == null) {
    
    
                return -1;
            }
            return (int) queue[first];
        }
        public int Rear() {
    
    
            if (queue[last] == null) {
    
    
                return -1;
            }
            return (int) queue[last];
        }
        public boolean isEmpty() {
    
    
            if (last == first && queue[last] == null) {
    
    
                return true;
            }
            return false;
        }
        public boolean isFull() {
    
    
            int lastIndex = last + 1;
            if (lastIndex == first || (lastIndex == size && first == 0)) {
    
    
                return true;
            }
            return false;
        }
}
/**
 * Your MyCircularQueue object will be instantiated and called as such:
 * MyCircularQueue obj = new MyCircularQueue(k);
 * boolean param_1 = obj.enQueue(value);
 * boolean param_2 = obj.deQueue();
 * int param_3 = obj.Front();
 * int param_4 = obj.Rear();
 * boolean param_5 = obj.isEmpty();
 * boolean param_6 = obj.isFull();
 */

Guess you like

Origin blog.csdn.net/weixin_38370441/article/details/115252537