[Day11]代码随想录

91 阅读3分钟

今日内容:20.有效的括号,1047.删除字符串中的所有相邻重复项,150.逆波兰表达式求值 代码随想录链接:代码随想录 (programmercarl.com)

20.有效的括号

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

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

这题用栈,遇到左括号就存入栈,遇到右括号就从栈里pop一个出来看看匹不匹配。

class Solution {
    public boolean isValid(String s) {
        Stack<Character> stack = new Stack<>();
        char[] ch = s.toCharArray();
        for(int i = 0; i < ch.length; i++){
            if(ch[i] == '(' || ch[i] == '{' || ch[i] == '['){
                stack.push(ch[i]);
            }
            if(ch[i] == ')'){        
                if(stack.isEmpty() || stack.pop() != '('){
                    return false;
                };
            }
            if(ch[i] == ']'){        
                if(stack.isEmpty() || stack.pop() != '['){
                    return false;
                };
            }
            if(ch[i] == '}'){        
                if(stack.isEmpty() || stack.pop() != '{'){
                    return false;
                }
            }
        }
        if(stack.isEmpty()){
            return true;
        }
        else{
            return false;
        }
    }
}

注意要判断stack是否非空,防止一些奇怪的情况。

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

给出由小写字母组成的字符串 S重复项删除操作会选择两个相邻且相同的字母,并删除它们。
在 S 上反复执行重复项删除操作,直到无法继续删除。
在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。

这道题给了“两个相邻且相同”而不是“两个及以上相邻且相同”,因此判断难度没那么高。入栈的时候进行判定,是否和下一个出栈元素相等.

class Solution {
    public String removeDuplicates(String s) {
        Stack<Character> stack = new Stack<>();
        char[] ch = s.toCharArray();
        int size = 0;
        for(int i = 0; i < ch.length; i++){
            if(!stack.isEmpty() && stack.peek() == ch[i]){
                stack.pop();
                size--;
                continue;
            }
            if(stack.isEmpty() || stack.peek() != ch[i]){
                stack.push(ch[i]);
                size++;
                continue;
            }
        }
        char[] res = new char[size];
        if(size == 0){
            return "";
        }
        while(size > 0){
            res[size - 1] = stack.pop();
            size--;
        }
        return String.valueOf(res);
    }
}

官方还给了一种双指针的写法。

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);
    }
}

一开始我在想双指针法会不会出现“删去两个及以上相邻且相同”而不是“删去两个相邻且相同”。

乍一眼好像会把相邻的相同元素全部删掉,但是经过手写验算,因为这个写法里先赋值ch[slow] = ch[fast];再判定if(slow > 0 && ch[slow] == ch[slow - 1]),因此刚好可以实现删去两个相邻且相同,当三个相邻的时候就会留下最后一个。

150.逆波兰表达式求值

给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。 请你计算该表达式。返回一个表示表达式值的整数。

一个表达式E的后缀形式可以如下定义:

(1)如果E是一个变量或常量,则E的后缀式是E本身。

(2)如果E是E1 op E2形式的表达式,这里op是任何二元操作符,则E的后缀式为E1'E2' op,这里E1'和E2'分别为E1和E2的后缀式。

(3)如果E是(E1)形式的表达式,则E1的后缀式就是E的后缀式。

如:我们平时写a+b,这是中缀表达式,写成后缀表达式就是:ab+

思路:新建一个表达式,如果当前字符为变量或者为数字,则压栈,如果是运算符,则将栈顶两个元素弹出作相应运算,结果再入栈,最后当表达式扫描完后,栈里的就是结果。

class Solution {
    public int evalRPN(String[] tokens) {
        Stack<Integer> stack = new Stack<>();
        for(String s : tokens){
            if("+".equals(s)){
               stack.push(stack.pop()+stack.pop());
            }else if("-".equals(s)){
                stack.push(-stack.pop()+stack.pop());
            }else if("*".equals(s)){
                stack.push(stack.pop()*stack.pop());
            }else if("/".equals(s)){
                int temp1 = stack.pop();
                int temp2 = stack.pop();
                stack.push(temp2 / temp1);
            }else{
                stack.push(Integer.valueOf(s));
            }  
        }      
    return stack.pop();
    }
}

结束