【代码随想录|刷题记录Day11】20.有效的括号、1047.删除字符串中的所有相邻重复项、150.逆波兰表达式求值

81 阅读2分钟

题目列表

  20.有效的括号

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

  150.逆波兰表达式求值

解题过程

1、20.有效的括号

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

有效字符串需满足:

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

思路: 将字符串中的元素入栈,一边入栈一边判断当前元素和已入栈元素是否匹配,如果是,就出栈;如果不是,就继续入栈。遍历完字符串后,判断栈是否为空。

class Solution {
    public boolean isValid(String s) {
        Deque<Character> deque = new LinkedList<>();
        char ch;
        for (int i = 0; i < s.length(); i++) {
            ch = s.charAt(i);
            //如果当前字符是左括号,就把右括号入栈
            if (ch == '(') {
                deque.push(')');
            } else if (ch == '{') {
                deque.push('}');
            } else if (ch == '[') {
                deque.push(']');
            } else if (deque.isEmpty() || deque.peek() != ch) { //当遇到右括号时,栈中一定要有相匹配的左括号,如果为空或者栈顶元素不匹配,就说明不是有效的括号
                return false;
            } else { //当前字符为右括号,判断是否和栈顶元素匹配(前面已经判断是否匹配,这里直接弹出就行)
                deque.pop();
            }
        }
        //字符串遍历完,栈为空,返回真
        return deque.isEmpty();
    }
}

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

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

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

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

思路: :有点像消消乐。还是用栈来做。

class Solution {
    public String removeDuplicates(String s) {
    
        Deque<Character> deque = new LinkedList<>();
        char ch;
        
        for (int i = 0; i < s.length(); i++) {
            ch = s.charAt(i);
            if (!deque.isEmpty() && ch == deque.peek()) {
                deque.pop();
                continue;
            }
            deque.push(ch);
        }
        
        String str = "";
        //弹出栈中剩余元素
        while (!deque.isEmpty()) {
            str = deque.pop() + str;
        }
        
        return str;
    }
}

用字符串做,可省略栈转化为字符串的过程

class Solution {
    public String removeDuplicates(String s) {
        // 将 res 当做栈
        // 也可以用 StringBuilder 来修改字符串,速度更快
        // StringBuilder res = new StringBuilder();
        StringBuffer res = new StringBuffer();
        // top为 res 的长度
        int top = -1;
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            // 当 top > 0,即栈中有字符时,当前字符如果和栈中字符相等,弹出栈顶字符,同时 top--
            if (top >= 0 && res.charAt(top) == c) {
                res.deleteCharAt(top);
                top--;
            // 否则,将该字符 入栈,同时top++
            } else {
                res.append(c);
                top++;
            }
        }
        return res.toString();
    }
}

用双指针来做

class Solution {
    public String removeDuplicates(String s) {
        char[] ch = s.toCharArray();
        int fast = 0;
        int slow = 0;
        while(fast < s.length()){
            // 直接用fast指针覆盖slow指针的值
            ch[slow] = ch[fast];
            // 遇到前后相同值的,就跳过,即slow指针后退一步,下次循环就可以直接被覆盖掉了
            if(slow > 0 && ch[slow] == ch[slow - 1]){
                slow--;
            }else{
                slow++;
            }
            fast++;
        }
        return new String(ch,0,slow);
    }
}

3、150.逆波兰表达式求值

给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。

请你计算该表达式。返回一个表示表达式值的整数。

注意:

  • 有效的算符为 '+''-''*''/'
  • 每个操作数(运算对象)都可以是一个整数或者另一个表达式。
  • 两个整数之间的除法总是 向零截断
  • 表达式中不含除零运算。
  • 输入是一个根据逆波兰表示法表示的算术表达式。
  • 答案及所有中间计算结果可以用 32 位 整数表示。

思路: 元素逐个入栈,遇到运算符,从栈中弹出两个元素,做相应运算后将结果入栈,依此类推,直到数组元素全部遍历完,这时栈中元素值就是答案。

class Solution {
    public int evalRPN(String[] tokens) {
        Deque<Integer> deque = new LinkedList<>();
        for (String str : tokens) {
            if (!"+".equals(str) && !"-".equals(str) && !"*".equals(str) && !"/".equals(str)) { //当前元素是数字
                deque.push(Integer.valueOf(str)); //字符转换为整数
            } else {
                int intB = deque.pop();
                int intA = deque.pop();
                if ("+".equals(str)) {
                    deque.push(intA + intB);
                } else if ("-".equals(str)) {
                    deque.push(intA - intB);
                } else if ("*".equals(str)) {
                    deque.push(intA * intB);
                } else {
                    deque.push(intA / intB);
                }
            }
        }
        return deque.pop();
    }
}

注意

  • leetcode中不能用==判断字符串是否相等;
  • 字符串到整数类型的转换。

总结

今天是栈的经典应用题目。