11打卡 栈与队列 2

文章介绍了如何用栈解决括号匹配问题,通过栈的入栈和出栈操作确定左右括号的配对。还讨论了如何用栈和队列处理字符串中的重复字符删除,以及逆波兰表达式的求值,强调了栈在这些问题中的应用和注意事项。
摘要由CSDN通过智能技术生成

思路

栈与队列相关的题目做的比较少,还真想不到用栈来解决,本题最核心的思路点在于怎么去确定两个括号是否能匹配,解决思路为遇到 左括号 就把相应的右括号放进去,当遇到右括号时,再对栈里的内容进行弹出匹配。

接下来是如何判断所有括号无法匹配,有以下三种情况

  • 左括号多余
  • 右括号多余
  • 左右括号不多余但是无法匹配

代码实现

    public boolean isValid(String s) {
        Stack<Character> stack = new Stack<>();
        char c;
        for (int i = 0; i < s.length(); i++) {
            c = s.charAt(i);
            if (c == '('){
                stack.push(')');
            } else if (c == '[') {
                stack.push(']');
            } else if (c == '{') {
                stack.push('}');
            }
            //以上的 if 条件实现了所有左括号的入栈
            //接下来判断 是否为空或者右括号与栈顶的左括号是都匹配
            else if (stack.isEmpty() || stack.peek() != c){
                return false;
            }else {
                stack.pop();
            }
        }
        //所有的右括号都判断完了 这是 看栈是否为空
        return stack.isEmpty();
    }

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

思路

要确保相邻的两个字母不一样,那么如果用栈的思想,在每一次压入一个新的元素入栈的时候,判断此时将要压入的元素和栈顶的元素是否相同,如果相同则将栈顶元素弹出,同时将当前元素“抛弃”。

那么什么时候将当前字母压入到栈里

  1. 目前栈是空的
  2. 目前字母和栈顶字母不相同

代码实现

写代码的时候才发现如果这里用栈的话,后面弹出之后,数组是反的,还要进行翻转。所以实际应该是用队列。

补充: 这样写其实就不需要翻转了

 while (!deque.isEmpty()) {
            str = deque.pop() + str;
        }

用栈实现(需要翻转)

    public String removeDuplicates(String s) {
        Stack<Character> chars = new Stack<>();
        for (int i = 0; i < s.length(); i++) {

            char ch = s.charAt(i);
            //什么时候压入? 目前栈是空的  目前字母和栈顶字母不相同
            if (chars.empty() || chars.peek() != ch) {
                chars.push(ch);
            } else {
                chars.pop();
            }
        }
        StringBuilder stringBuilder = new StringBuilder();
        while (!chars.empty()){
            stringBuilder.append(chars.pop());
        }
        stringBuilder.reverse();
        return stringBuilder.toString();
    }

 栈的一个注意点

当栈为空的时候 empty方法的返回值是true 所以以上需求中应该用的是  !char.empty() 

用队列实现

首先明确java中new的方式

Deque<String> animal1 = new ArrayDeque<>();

Deque<String> animal2 = new LinkedList<>();

  1. 底层数据结构

    • ArrayDeque:使用可调整大小的数组来存储元素,因此其操作效率更高,特别是在随机访问元素和尾部添加/删除元素的情况下。
    • LinkedList:使用双向链表来存储元素,这使得在列表中间插入和删除元素的操作更为高效。
  2. 性能特点

    • ArrayDeque 在大多数情况下具有更好的性能,因为它的底层数组支持随机访问,因此可以在O(1)时间复杂度内对队列的头部和尾部进行操作。
    • LinkedList 对于频繁的插入和删除操作,尤其是在列表中间,性能可能会更好,因为链表的结构使得插入和删除操作的时间复杂度为O(1)。
  3. 内存占用

    • ArrayDeque 在一般情况下会占用更少的内存,因为它使用的是一个连续的数组。
    • LinkedList 通常会占用更多的内存,因为除了存储元素值之外,还需要存储每个元素的指向前后元素的指针。
  4. 功能特性

    • 由于ArrayDeque基于数组,它不支持元素的空值(null);而LinkedList可以存储空值。
    • ArrayDeque 不支持在中间位置的O(1)时间内的插入和删除操作。

L0150. 逆波兰表达式求值

思路

对于模拟题 明确规则之后就比较容易写出代码。

那么这里的规则:从左到右对表达式进行遍历,如果遇到数字就进栈,如果是符号就取出栈顶的两个元素进行运算,然后把运算的结果压入栈。

代码实现

需要注意的点时 减法和除法运算需要分前后

    public int evalRPN(String[] tokens) {

        Stack<Integer> stack = new Stack<>();

        for (String str : tokens) {
            if (str.equals("+")) {
                stack.push(stack.pop() + stack.pop());

            } else if (str.equals("*")) {
                stack.push(stack.pop() * stack.pop());
            } else if (str.equals("-")) {
                Integer temp1 = stack.pop();
                Integer temp2 = stack.pop();
                stack.push(temp2 - temp1);
            } else if (str.equals("/")) {
                Integer temp1 = stack.pop();
                Integer temp2 = stack.pop();
                stack.push(temp2 / temp1);
            }else {
                stack.push(Integer.valueOf(str));
            }
        }
        return stack.pop();
    }

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

思路

当前字母与栈顶相同时,扔掉当前字母并且弹出栈顶

值得学习的思路是在进行字符串连接时,“倒着拼接”可以避免最后的reverse。

代码实现

    public static String removeDuplicates(String s) {
        Deque<Character> deque = new ArrayDeque<>();
        for (int i = 0; i < s.length(); i++) {
            char ch = s.charAt(i);
            if (deque.isEmpty() || ch != deque.peek()) {
                deque.push(ch);
            } else {
                deque.pop();
            }
        }
        String res = "";
        while (!deque.isEmpty()) {
            res = deque.pop() + res;
        }
        return res;
//        StringBuilder stringBuilder = new StringBuilder();
//        while (!deque.isEmpty()){
//            stringBuilder.append(deque.pop());
//        }
//        return stringBuilder.reverse().toString();
    }

  • 18
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值