LeetCode刷题:栈与队列

用2个queue实现stack

https://leetcode-cn.com/problems/implement-stack-using-queues/
在这里插入图片描述

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. 三元表达式解析器

https://leetcode-cn.com/problems/ternary-expression-parser/
在这里插入图片描述

Key point:

  1. Character.isDigit判断数字
  2. 判断处理(进栈出栈)的标志为?以及之后谁进栈谁出栈,最后留下的就是答案
    只需要一次遍历即可
    在这里插入图片描述

71. 简化路径

在这里插入图片描述

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. 去除重复字母

在这里插入图片描述

要点:
贪心 + stack

  1. stack内存放的都是经过贪心算法校验的当前最优解
    每次需要判断的是即将处理的字符是否要加入,是否能够替换之前的重复字符
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;
    }
}

队列

核心要点:

  1. 三个下标:size、first、last
    想清楚first与last代表的实际意义:代表确切的存在元素的下标而不是该位置的下一个
    first之间的关系是:仅有一种情况会重合。数组中只有一个元素时。
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();
 */

猜你喜欢

转载自blog.csdn.net/weixin_38370441/article/details/115252537