算法day09-栈与队列(1)

目录

  1. 力扣232. 用栈实现队列
  2. 力扣225. 用队列实现栈
  3. 力扣20. 有效的括号
  4. 力扣1047. 删除字符串中的所有相邻重复项

 一、用栈实现队列

  主要思路:我们使用两个栈来实现一个队列的功能:其中一个作为输入栈,用于接收通过 push 操作传入的数据;另一个作为输出栈,专门用于处理 poppeek 操作。当需要执行 poppeek 时,如果输出栈为空,我们就将输入栈中的所有元素依次弹出,并按顺序压入输出栈。这样一来,输出栈的栈顶元素就对应了队列的队首,实现了先进先出的队列行为。

class MyQueue {
    Deque<Integer> inStack;
    Deque<Integer> outStack;

    public MyQueue() {
        //初始化两个栈
        inStack = new ArrayDeque<Integer>();
        outStack = new ArrayDeque<Integer>();
    }
    
    public void push(int x) {
        inStack.push(x);        
    }
    
    public int pop() {
        if(outStack.isEmpty()){         //当辅助栈里面镁元素时,要把入栈的元素倒压进出栈
            in2out();
        }
        return outStack.pop();
    }
    
    public int peek() {
        if(outStack.isEmpty()){
            in2out();
        }
        return outStack.peek();
    }
    
    public boolean empty() {
        return inStack.isEmpty() && outStack.isEmpty();
    }

    public void in2out(){
        while(!inStack.isEmpty()){
            outStack.push(inStack.pop());       //把入栈的元素压进出栈
        }
    }
}
//时间复杂度:O(1)
//空间复杂度:O(N)

二、用队列实现栈

  主要思路:这里可以用两个队列来实现一个栈。首先我们定义两个队列,一个用作辅助。当我们push一个元素时,先将元素放到队列2中,然后将队列 1的所有元素出队加到队列2的末尾,然后再将队列2的所有元素出队放到队列1中。这样可以确保每次入栈操作都确保队列1的前端为栈顶元素,出栈和获得栈顶元素操作都可以简单实现。

class MyStack {
    Queue<Integer> queue1;
    Queue<Integer> queue2;
    public MyStack() {
        queue1 = new LinkedList<Integer>();
        queue2 = new LinkedList<Integer>();
    }
    
    public void push(int x) {
        queue2.offer(x);
        while(!queue1.isEmpty()){
            queue2.offer(queue1.poll());
        }

        //交换queue1和queue2的元素
        Queue<Integer> temp = queue1;
        queue1 = queue2;
        queue2 = temp;
    }
    
    public int pop() {
        return queue1.poll();
    }
    
    public int top() {
        return queue1.peek();
    }
    
    public boolean empty() {
        return queue1.isEmpty();
    }
}
//时间复杂度:O(n)入栈,O(1):出栈、查看队首元素、判断为空
//空间复杂度:O(N)

  方法二:用一个队列也可以实现栈。只需要修改:在每次入栈的时候,先统计此时队列的长度,然后将元素加入到队列的尾部,然后把本来有的几个元素都从对头弹出并从队尾压入,这样就能保持每次push 的元素都在最开头。

class MyStack {
    Queue<Integer> queue;

    public MyStack() {
        queue = new LinkedList<Integer>();
    }
    
    public void push(int x) {
        int n = queue.size();
        queue.offer(x);
        for (int i = 0; i < n; i++) {
            queue.offer(queue.poll());
        }
    }
    
    public int pop() {
        return queue.poll();
    }
    
    public int top() {
        return queue.peek();
    }

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

三、有效的括号

   主要思路:首先用一个哈希表记录右-左括号匹配对,然后去遍历输入的字符串,当前字符若是左括号则直接压入栈,若是右括号则进行判断:若栈为空,或者这个右括号与此时栈顶元素不匹配,则说明此字符串不是有效括号字符串。否则弹出字符。

class Solution {
    public boolean isValid(String s) {
        int n = s.length();
        if( n % 2 == 1 ){       //如果长度为奇数,则一定不能匹配
            return false;
        }

        Map<Character,Character> map = new HashMap<>();
        map.put(')', '(');
        map.put(']', '[');
        map.put('}', '{');
        Deque<Character> stack = new ArrayDeque<>();
        for(int i=0; i<n; i++){
            char ch = s.charAt(i);
            if(map.containsKey(ch)){        //如果遇到右括号
                //若栈为空,或者这个右括号与此时栈顶元素不匹配
                if(stack.isEmpty() || map.get(ch) != stack.peek()){
                    return false;
                }
                stack.pop();
            }else{
                //如果遇到的是左括号
                stack.push(ch);
            }
        }
        //最后根据栈是否为空来判断是不是都匹配完了
        return stack.isEmpty();
    }
}
//时间复杂度:O(N)
//空间复杂度:O(N)

四、删除字符串中的所有相邻重复项

  主要思路:先遍历字符串,然后比较当前元素是否和栈顶元素相同,相同则把栈顶元素弹出,不相同则压入栈。

 

class Solution {
    public String removeDuplicates(String s) {
        Deque<Character> stack = new ArrayDeque<>();
        int n = s.length();
        for(int i=0; i<n; i++){
            char ch = s.charAt(i);
            if(!stack.isEmpty() && ch == stack.peek()){
                stack.pop();
            }else{
                stack.push(ch);
            }
        }
        StringBuilder sb = new StringBuilder();
        for(char num : stack){
            sb.append(num);
        }
        return sb.reverse().toString();
    }
}
//时间复杂度:O(n)
//空间复杂度:O(n)

 

posted @ 2025-05-03 16:29  筱倩  阅读(232)  评论(0)    收藏  举报