Day 11 | 232.用栈实现队列 & 225. 用队列实现栈 & 20. 有效的括号 & 1047. 删除字符串中的所有相邻重复项

232.用栈实现队列

请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty):

void push(int x) 将元素 x 推到队列的末尾
int pop() 从队列的开头移除并返回元素
int peek() 返回队列开头的元素
boolean empty() 如果队列为空,返回 true ;否则,返回 false

解题思路:

由于栈是先进后出,队列是先进先出。因此定义两个栈,所有元素进入第一个栈In后,再全部进入第二个栈Out,这样便可实现先进入的元素也可以先出。

自定义一个方法dumpStackIn——所有进入stackIn的元素全部压入stackOut栈中(注意要判断out栈是否为空,为空元素才能入栈,out栈若不为空元素就入栈,则新入栈的元素会先出来)。

两点注意:

进入stackIn的元素,要全部进入stackOut中

②只有stackOut中没有元素时,元素才能进入stackOut中,否则会破坏出栈顺序。

实现四个函数:

push:直接stackIn.push(x)即可。

pop:首先调用dumpStackIn方法,若原out栈不为空,则直接返回原栈的栈顶,否则将in栈的元素压入out栈后返回栈顶元素。

peek:同pop。

empty:当stackIn与stackOut同时为空时,则队列为空。

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() {
        dumpStackIn();
        return stackOut.pop();
    }
    
    public int peek() {
        dumpStackIn();
        return stackOut.peek();
    }
    
    public boolean empty() {
        return stackIn.isEmpty()&&stackOut.isEmpty();
    }
    public void dumpStackIn(){
        //如果out里还有元素(非空),则in元素不入out栈 否则会破坏out栈原有出栈顺序,即新入的out元素比之前还没有出out栈的元素先出out栈
        if(!stackOut.isEmpty()){
            return;
        }
        //若out为空则可以入栈,将in里的所有元素都加入到out栈中
        while(!stackIn.isEmpty()){
            stackOut.push(stackIn.pop());
        }
        return;
      }
}

225. 用队列实现栈

请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。

实现 MyStack 类:

void push(int x) 将元素 x 压入栈顶。
int pop() 移除并返回栈顶元素。
int top() 返回栈顶元素。
boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。

我看懂了解题思路,代码实现部分还有一些问题,下次补上。。

//1.9补充:

本题就是将一个队列q2视为辅助队列,用来实现q1正确的出栈顺序,入栈时进行操作,出栈只需要出q1存放的正确顺序的元素即可。

元素入队列时首先将元素存放在辅助队列q2中,若q1不为空,则将q1中所有元素加入到q2中。此时q1之前加入的元素就相当于q2后加入的元素,实现了先进后出。最后交换q1和q2。q1依旧代表正确顺序,q2为空。

class MyStack {
    Queue<Integer> queue1; // 和栈中保持一样元素的队列
    Queue<Integer> queue2; // 辅助队列

    /** Initialize your data structure here. */
    public MyStack() {
        queue1 = new LinkedList<>();
        queue2 = new LinkedList<>();
    }
    
    public void push(int x) {
        queue2.offer(x);//先将元素存放在q2,暂时存放正确顺序
        while(!queue1.isEmpty()){
            queue2.offer(queue1.poll());//若q1非空,则将q1中的元素加入到q2中。此时q1之前入队列的元素变为q2后入队列的元素成为后出元素,实现了先进后出
        }
        Queue<Integer> temp;
        temp=queue1;
        queue1=queue2;
        queue2=temp;//交换q1和q2两个队列,此时q1为正确出栈顺序(先进后出),q2为空
    }
    
    public int pop() {
        return queue1.poll();
    }
    
    public int top() {
        return queue1.peek();
    }
    
    public boolean empty() {
        return queue1.isEmpty()&&queue2.isEmpty();
    }
}

20. 有效的括号

给定一个只包括 '(',')','{','}','[',']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
每个右括号都有一个对应的相同类型的左括号。

解题思路:括号匹配是使用栈解决的经典问题。由于栈是先进后出。因此可以让所有左括号入栈(入相应的右括号),然后最后入栈的左括号会最先进行匹配。

不匹配的三种情况:

①左括号多

②右括号多

③类型不匹配

让所有左括号入栈,若当前元素为右括号时,让相应的左括号(栈顶)出栈,若类型不匹配(③),则返回false;

若当前元素为右括号时栈为空(②),说明没有足够左括号匹配,返回false;

若所有元素入栈后栈不为空(①),说明没有足够右括号匹配,则返回false。

下面是我写的代码,还不是很优化:

    public boolean isValid(String s) {
        Stack<Character> stack = new Stack<>();
        if (s.length() % 2 != 0) {
            return false;
        }
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (c == '(') {
                stack.push(')');
            }
            else if (c == '[') {
                stack.push(']');
            }
            else if (c == '{') {
                stack.push('}');
            }
            if (c == ')') {
                if (!stack.isEmpty()&&stack.pop() == ')') {
                    continue;
                } else {
                    return false;
                }
            }
            if (c == ']') {
                if (!stack.isEmpty()&&stack.pop() == ']') {
                    continue;
                } else {
                    return false;
                }
            }
            if (c == '}') {
                if (!stack.isEmpty()&&stack.pop() == '}') {
                    continue;
                } else {
                    return false;
                }
            }
        }
        if (stack.isEmpty()) {
            return true;
        } else {
            return false;
        }

    }

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

给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。

在 S 上反复执行重复项删除操作,直到无法继续删除。

在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。

输入:"abbaca"
输出:"ca"

本题为匹配问题,栈的应用。

方法一:直接用栈解决(复杂度较高)

class Solution {
    public String removeDuplicates(String s) {
                Stack<Character> stack=new Stack<>();
        for(int i=0;i<s.length();i++){
            char c=s.charAt(i);
            if(stack.isEmpty()||stack.peek()!=c){
                stack.push(c);
            }else if(stack.peek()==c){
                stack.pop();
            }
        }
        String ss="";
        int size= stack.size();
        for(int i=0;i<size;i++) {
            ss += stack.pop();
        }
       return new StringBuffer(ss).reverse().toString();
    }
}

方法二:用字符串模拟栈

该方法降低了复杂度,下面是我自己写的,由于时间不够了还没看优化后的。。下次补上!

        StringBuffer sb = new StringBuffer(s);
        int top = 0;
        int len = sb.length();
        for (int i = 0; i < len; i++) {
            char t = sb.charAt(top);
            if (i == 0 || (top != 0 && sb.charAt(top) != sb.charAt(top - 1))) {
                top++;
            } else if (top!=0 && sb.charAt(top) == sb.charAt(top - 1)) {
                sb.deleteCharAt(top);
                sb.deleteCharAt(top - 1);
                top -= 1;
            }else if(top==0){top++;}

        }
        return sb.toString();

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值