代码随想录刷题-栈

232.用栈实现队列


题目

使用栈实现队列的下列操作:

  • push(x) -- 将一个元素放入队列的尾部。

  • pop() -- 从队列首部移除元素。

  • peek() -- 返回队列首部的元素。

  • empty() -- 返回队列是否为空。

思路

  • 栈是先入后出,队列是先入先出,可以使用两个栈来表示一个队列

  • 如果是push,直接push进stackIn即可

  • 如果pop,看stackOut是否为空,不为空从stackOut出元素,为空就把stackIn所有元素倒入stackOut中

代码

class MyQueue {
    Stack stackIn;
    Stack stackOut;

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

    //放入元素较为简单,直接把元素放入入栈即可
    public void push(int x) {
        stackIn.push(x);
    }

    //调用dumpStackIn()方法后pop即可
    public int pop() {
        this.dumpStackIn();
        return stackOut.pop();
    }

    //注意可以复用pop方法,弹出之后再把元素放回去,然后再返回元素
    public int peek() {
        int peek = this.pop();
        stackOut.push(peek);
        return peek;
    }

    //如果入栈和出栈都为空,则队列为空
    public boolean empty() {
        return stackIn.isEmpty() && stackOut.isEmpty();
    }

    //私有化一个方法,如果出栈不为空,则直接返回;
    //如果出栈为空,就把入栈的所有元素依次放入出栈中
    private void dumpStackIn() {
        if (!stackOut.isEmpty()) {
            return;
        }
        while (!stackIn.isEmpty()) {
            int pop = stackIn.pop();
            stackOut.push(pop);
        }
    }
}

反思

  • 用栈可以实现队列,使用两个栈即可

225. 用队列实现栈


题目

使用队列实现栈的下列操作:

  • push(x) -- 元素 x 入栈

  • pop() -- 移除栈顶元素

  • top() -- 获取栈顶元素

  • empty() -- 返回栈是否为空

思路

  • 栈和队列的区别是

  • 栈是先进去的元素先出来,队列是先进去的元素后出来

  • 所以可以这样处理,使用一个队列,每次加入元素之后,都把其他元素依次取出再加入队列

  • 这样可以使得这个元素"直接插入到队头",在进行后续pop和peek操作时可以直接拿到队头的元素

代码

class MyStack {

    Queue quene; //这个stack类里面有一个quene属性

    public MyStack() {
        quene = new LinkedList<>(); //quene和deque都是接口,创建实现类LinkedList对象即可
    }

    //添加元素的思路复杂些,加入之后,把除了这个元素其他的元素都重新输出并加入quene
    //这样保证新加入的这个元素位于队列的头
    public void push(int x) {
        int size = quene.size();
        quene.add(x);
        while (size-- > 0){
            Integer poll = quene.poll();
            quene.add(poll);
        }
    }

    //后续的pop和peek直接调用队列的方法即可
    public int pop() {
        return quene.poll();
    }

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

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

反思

  • 其实也可以使用两个队列或者Deque实现

  • 最重要的就是加入元素的时候,怎么保证这个元素在队头?

  • 把其他元素取出再加入队列即可

20. 有效的括号


题目

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

有效字符串需满足:

  • 左括号必须用相同类型的右括号闭合。

  • 左括号必须以正确的顺序闭合。

  • 注意空字符串可被认为是有效字符串。

思路

  • 这种处理对称性的问题,可以使用栈来解决

  • 每次加入的元素有几种情况:

  • 如果是左括号,就直接加入对应的右括号即可

  • 如果是右括号,这时候按道理应该从栈中pop元素,但如果这时候栈空(右括号多),直接返回false

  • 栈不空,就比较栈peek的元素和待比较的右括号是否相等,不等直接返回false

  • 相等,就pop元素,进行下一次循环

  • 循环结束之后,由于可能左括号多,也就是这时候栈非空,也返回false

代码

class Solution {
    public boolean isValid(String s) {

        char[] chars = s.toCharArray();
        //对称性问题可以考虑使用栈解决
        Stack stack = new Stack<>();

        //遍历字符串对应的字符数组
        for (int i = 0; i < chars.length; i++) {

            //如果是左括号,push对应的右括号,这样判断起来简单
            if (chars[i] == '(') {
                stack.push(')');
            } else if (chars[i] == '[') {
                stack.push(']');
            } else if (chars[i] == '{') {
                stack.push('}');

            //如果不是左括号,是右括号,那么这时候先看栈是否空,再比较元素
            } else if (stack.isEmpty() || stack.peek() != chars[i]) {
                return false;

            //相等就pop元素,继续循环
            } else {
                stack.pop();
            }
        }
        //循环结束后,避免出现左括号多的情况,判断栈是否为空
        return stack.isEmpty();
    }
}

反思

  • 这个题观察到对称性,考虑栈的实现方式

  • 难点在于讨论情况较多,要有逻辑地想,左括号右括号,谁多水少,如何判断

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


题目

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

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

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

思路

  • 还是对称问题,考虑栈

  • 每个元素,如果栈空或者匹配不上,入栈(注意栈空在前考虑,避免空栈匹配报异常)

  • 否则出栈

  • 最后返回字符串

代码

  • 方式一:使用stack / ArrayDeque / LinkedList

class Solution {
    public String removeDuplicates(String s) {

        //使用stack也行,linkedlist也行
        ArrayDeque stack = new ArrayDeque<>();
        char[] chars = s.toCharArray();

        for (int i = 0; i < chars.length; i++) {
            if (stack.isEmpty() || stack.peek() != chars[i]){ //栈空或者peek()的元素与待比较的元素不等
                stack.push(chars[i]);
            }else {
                stack.pop();//比较后相等,pop()元素
            }
        }
        String str = "";//略麻烦的是,需要把栈转为字符串
        while (!stack.isEmpty()){
            str = stack.pop() + str;//注意,反向拼接
        }
        return str;
    }
}
  • 方式二:直接使用StringBuffer

class Solution1 {
    public String removeDuplicates(String s) {

        char[] chars = s.toCharArray();
        StringBuffer res = new StringBuffer();
        int top = -1;//栈顶初始为-1

        for (int i = 0; i < chars.length; i++) {
            if (top >= 0 && res.charAt(top)== chars[i]){//栈有元素且匹配上,才会取出
                res.deleteCharAt(top);
                top--;
            }
            else{
                res.append(chars[i]);//否则,加元素即可
                top++;
            }
        }
        return res.toString();
    }
}

反思

  • 可以发现直接使用字符串快了很多,使用StringBuilder可以更快

  • 最后需要考虑拼接字符串时反转的问题,注意细节

150. 逆波兰表达式求值


题目

  • 根据 逆波兰表示法,求表达式的值。

有效的运算符包括 + , - , * , / 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。

思路

  • 逆波兰表达式求值是典型的使用栈处理的问题

  • 遍历数组,遇到数字直接进栈

  • 遇到符号,把栈顶的两个元素运算(后pop出的对先pop出的运算),之后再入栈

  • 最后栈内只有一个元素,出栈即可

代码

class Solution {
    public int evalRPN(String[] tokens) {
        LinkedList stack = new LinkedList<>();
        for (int i = 0; i < tokens.length; i++) {
            String str = tokens[i];

            int ans;
            if (str.equals("+")) {
                stack.push(stack.pop() + stack.pop());
            } else if (str.equals("-")) {
                stack.push(-stack.pop() + stack.pop()); //注意减法的特殊处理
            } else if (str.equals("*")) {
                stack.push(stack.pop() * stack.pop());
            } else if (str.equals("/")) { //注意除法的特殊处理,先出的是除数,后出的是被除数
                int temp1 = stack.pop();
                int temp2 = stack.pop();
                stack.push(temp2 / temp1);
            }else {
                stack.push(Integer.valueOf(str));
            }
        }
        return stack.pop();
    }
}

反思

  • 栈部分结束,看到对称想一下栈能否实现!

  • 后缀表达式对计算机来说是非常友好的,学会逆波兰表达式的求值

你可能感兴趣的:(java,算法,数据结构)