LeetCode —— 栈与队列

持续更新中................

232. 用栈实现队列

请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):①void push(int x) 将元素 x 推到队列的末尾;②int pop() 从队列的开头移除并返回元素;③int peek() 返回队列开头的元素;④boolean empty() 如果队列为空,返回 true ;否则,返回 false

class MyQueue {
    Stack<Integer> stackIn;
    Stack<Integer> stackOut;

    public MyQueue() {
        stackIn = new Stack<>();
        stackOut = new Stack<>();
    }

    public void push(int x) {
        stackIn.push(x);
    }

    public int pop() {
        if(stackOut.isEmpty()){
            while(!stackIn.isEmpty()){
                stackOut.push(stackIn.pop());
            }
        }
        return stackOut.pop();
    }

    public int peek() {
        if(stackOut.isEmpty()){
            while(!stackIn.isEmpty()){
                stackOut.push(stackIn.pop());
            }
        }
        return stackOut.peek();
    }

    public boolean empty() {
        return stackIn.isEmpty() && stackOut.isEmpty();
    }
}

225. 用队列实现栈

请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty):①void push(int x) 将元素 x 压入栈顶;②int pop() 移除并返回栈顶元素。
③int top() 返回栈顶元素;④boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。

//使用两个Queue
class MyStack {
    Queue<Integer> queue1;
    Queue<Integer> queue2;

    public MyStack() {
        queue1 = new LinkedList<>();
        queue2 = new LinkedList<>();
    }

    public void push(int x) {
        queue2.offer(x); // 先放在辅助队列中
        while (!queue1.isEmpty()){
            queue2.offer(queue1.poll());
        }
        Queue<Integer> queueTemp;
        queueTemp = queue1;
        queue1 = queue2;     //将元素都放到queue1中
        queue2 = queueTemp;
    }

    public int pop() {
        return queue1.poll();
    }

    public int top() {
        return queue1.peek();
    }

    public boolean empty() {
        return queue1.isEmpty();
    }
}
//使用一个Queue
class MyStack {
    Queue<Integer> queue;

    public MyStack() {
        queue = new LinkedList<>();
    }

    public void push(int x) {
        queue.offer(x);
        int size = queue.size();
        while(size > 1){
            queue.offer(queue.poll());
            size--;
        }
    }

    public int pop() {
        return queue.poll();
    }

    public int top() {
        return queue.peek();
    }

    public boolean empty() {
        return queue.isEmpty();
    }
}

20. 有效的括号

给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。有效字符串需满足:①左括号必须用相同类型的右括号闭合;②左括号必须以正确的顺序闭合;③每个右括号都有一个对应的相同类型的左括号。

示例1:输入:s = "([]{})"         输出:true

示例2:输入:s = "([)]"         输出:false

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

1047. 删除字符串中的所有相邻重复项

给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。在 S 上反复执行重复项删除操作,直到无法继续删除。在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。

示例1:输入:"abbaca"         输出:"ca"

//执行用时141ms
class Solution {
    public String removeDuplicates(String s) {
        Deque<Character> deque = new ArrayDeque<>();
        for(int i = 0; i < s.length(); i++){
            char c = s.charAt(i);
            if(deque.isEmpty() || deque.peek() != c){
                deque.push(c);
            }else{
                deque.pop();
            }
        }
        String result = "";
        while(!deque.isEmpty()){
            result = deque.pop() + result;
        }
        return result;
    }
}
//执行用时10ms
class Solution {
    public String removeDuplicates(String s) {
        StringBuilder sb = new StringBuilder();
        int top = -1;
        for(int i = 0; i < s.length(); i++){
            char c = s.charAt(i);
            if(top == -1 || sb.charAt(top) != c){
                sb.append(c);
                top++;
            }else{
                sb.deleteCharAt(top);
                top--;
            }
        }
        return sb.toString();
    }
}
//执行用时3ms
class Solution {
    public String removeDuplicates(String s) {
        char[] chars = s.toCharArray();
        int slow = 0;
        for(int fast = 0; fast < chars.length; fast++){
            chars[slow] = chars[fast];
            if(slow > 0 && chars[slow] == chars[slow - 1]){
                slow--;
            }else{
                slow++;
            }
        }
        return new String(chars, 0, slow);
    }
}

150. 逆波兰表达式求值

据 逆波兰表示法,求表达式的值。有效的算符包括 +、-、*、/ 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。注意 两个整数之间的除法只保留整数部分。

示例1:输入:tokens = ["2","1","+","3","*"]         输出:9         解释:((2 + 1) * 3) = 9

示例2:输入:tokens = ["4","13","5","/","+"]         输出:6         解释:(4 + (13 / 5)) = 6

class Solution {
    public int evalRPN(String[] tokens) {
        Deque<Integer> deque = new LinkedList<>();
        for(String s : tokens){
            if("+".equals(s)){
                deque.push(deque.pop() + deque.pop());
            }else if("-".equals(s)){
                deque.push(-deque.pop() + deque.pop());
            }else if("*".equals(s)){
                deque.push(deque.pop() * deque.pop());
            }else if("/".equals(s)){
                int temp1 = deque.pop();
                int temp2 = deque.pop();
                deque.push(temp2 / temp1);
            }else{
                deque.push(Integer.valueOf(s));
            }
        }
        return deque.pop();
    }
}

239. 滑动窗口最大值

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

示例1:输入:nums = [1,3,-1,-3,5,3,6,7], k = 3         输出:[3,3,5,5,6,7]

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        int[] result = new int[nums.length - k + 1];
        int index = 0;

        Deque<Integer> deque = new ArrayDeque<>();   //使用队列存储下标
        for(int i = 0; i < nums.length; i++){
            //在[i - k + 1, 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){
                result[index++] = nums[deque.peek()];
            }
        }
        return result;
    }
}
class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        int[] array = new int[nums.length - k + 1];
        PriorityQueue<int[]> pq = new PriorityQueue<>((pari1, pari2) -> pari2[0] - pari1[0]);
        for(int i = 0; i < k; i++){
            pq.offer(new int[]{nums[i], i});
        }
        array[0] = pq.peek()[0];
        for(int i = k; i < nums.length; i++){
            pq.offer(new int[]{nums[i], i});
            while(pq.peek()[1] < i - k + 1){
                pq.poll();
            }
            array[i - k + 1] = pq.peek()[0];
        }
        return array;
    }
}

347. 前K个高频元素

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

示例1:输入: nums = [1,1,1,2,2,3], k = 2         输出: [1,2]

//大顶堆
class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        Map<Integer, Integer> map = new HashMap<>();
        for(int num : nums){
            map.put(num, map.getOrDefault(num, 0) + 1);
        }

        //在优先队列中存储二元组(num,cnt),cnt表示元素值num在数组中的出现次数
        //大顶堆在加入元素时需要对所有元素进行排序
        PriorityQueue<int[]> pq = new PriorityQueue<>((pair1, pair2) -> pair2[1]-pair1[1]);
        for(Map.Entry<Integer, Integer> entry : map.entrySet()){
            pq.add(new int[]{entry.getKey(), entry.getValue()});
        }
        
        int[] result = new int[k];
        for(int i = 0; i < k; i++){
            result[i] = pq.poll()[0];
        }
        return result;
    }
}
//小顶堆
class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        Map<Integer, Integer> map = new HashMap<>();
        for(int num : nums){
            map.put(num, map.getOrDefault(num, 0) + 1);
        }

        //在优先队列中存储二元组(num,cnt),cnt表示元素值num在数组中的出现次数
        //小顶堆只需要维持k个元素有序
        PriorityQueue<int[]> pq = new PriorityQueue<>((pair1, pair2) -> pair1[1]-pair2[1]);
        for(Map.Entry<Integer, Integer> entry : map.entrySet()){
            if(pq.size() < k){
                pq.add(new int[]{entry.getKey(), entry.getValue()});
            }else{
                if(entry.getValue() > pq.peek()[1]){
                    pq.poll();
                    pq.add(new int[]{entry.getKey(), entry.getValue()});
                }
            }
        }

        int[] result = new int[k];
        for(int i = k-1; i >= 0; i--){
            result[i] = pq.poll()[0];
        }
        return result;
    }
}

用栈来实现LRU

public class LRU {
    private int capacity;
    private Stack<Integer> stack;

    public LRU(int capacity) {
        this.capacity = capacity;
        stack = new Stack<>();
    }

    public int get(int key) {
        if(stack.contains(key)) {
            stack.removeElement(key);
            stack.push(key);
            return key;
        }
        return -1;
    }

    public void put(int key) {
        if(stack.contains(key)) {
            stack.removeElement(key);
        }else if(stack.size() == capacity) {
            stack.remove(0);
        }
        stack.push(key);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值