力扣20:有效的括号

原题链接
这道题给了三个提示:

  1. 用递归
  2. 每找到一组对应的括号就去除
  3. 因为问题是递归结构的,所以可以考虑使用栈

使用栈感觉是不言自明的解法。

class Solution {
    Map<Character,Character> parenthesesPair = new HashMap<Character,Character>(){{
       put(')','(');
       put(']','[');
       put('}','{');
    }};
    public boolean isValid(String s) {
        if (parenthesesPair.containsKey(s.charAt(0))||s.length()<=1)//第一个字符是右括号或者只有一个字符都不行
            return false;
        Deque<Character> stack = new ArrayDeque<>();//栈用于存储所有的左括号
        stack.push(s.charAt(0));//第一个字符必然是左字符且长度必然大于等于2
        for(int i = 1;i<s.length();i++){
            if(parenthesesPair.containsKey(s.charAt(i))){//说明是任一种括号的后半部分,右括号就判断匹配
                if (stack.isEmpty())
                    return false;
                else if(!stack.peek().equals(parenthesesPair.get(s.charAt(i))))
                    //除了栈里面匹配不到左括号,还要考虑栈里面根本没有括号,必然报异常。我考虑使用短路或
                    //收获:出现equals的条件判断的时候一定要注意空指针异常!
                    return false;
                stack.pop();//如果匹配必须弹出
            }else//任一种括号的左半部分,直接推入
                stack.push(s.charAt(i));

        }
        if (!stack.isEmpty())//说明有些左括号没有匹配的右括号
            return false;
        return true;
    }
}

力扣20:有效的括号_第1张图片

官方解答

class Solution {
    public boolean isValid(String s) {
        int n = s.length();
        if (n % 2 == 1) {
            return false;
        }

        Map<Character, Character> pairs = new HashMap<Character, Character>() {{
            put(')', '(');
            put(']', '[');
            put('}', '{');
        }};
        Deque<Character> stack = new LinkedList<Character>();
        for (int i = 0; i < n; i++) {
            char ch = s.charAt(i);
            if (pairs.containsKey(ch)) {
                if (stack.isEmpty() || stack.peek() != pairs.get(ch)) {
                    return false;
                }
                stack.pop();
            } else {
                stack.push(ch);
            }
        }
        return stack.isEmpty();
    }
}

可以看到我的代码慢的原因是if判断的逻辑过于复杂。官方解答的判断逻辑:

  1. 长度为奇数一定存在不匹配的括号
  2. 遍历到右括号,如果栈为空或者栈顶括号不匹配,说明存在不匹配的括号,直接返回false
  3. 遍历到左括号就压入栈

所有括号匹配完的话,那么栈就一定是空的。

我的可以修改的地方其实不少。

if (!stack.isEmpty())//说明有些左括号没有匹配的右括号
	return false;
return true;

直接改成:

return stack.isEmpty();

其实是显而易见的。
另外parenthesesPair.containsKey(s.charAt(0)),也就是第一个字符是右括号实际上可以不用判断,就算是右括号,推进去发现栈为空,也会直接return false。第一个条件可以直接检验输入长度是否为奇数。

补充

java&&与||的优先级
ArrayList、ArrayDeque与LinkedList区别。 ArrayList、ArrayDeque内部以数组的形式保存集合中的元素,因此随机访问元素时有较好的性能;而LinkedList内部以链表的形式来保存集合中的元素,因此随机访问集合中的元素时虽然性能较差,但在插入、删除元素时性能非常出色。
Why is ArrayDeque better than LinkedList。这篇stackoverflow的问答提到:在双向队列(Deque)的首尾端添加和移除元素时使用ArrayQueue更佳;要在循环的单次迭代中移除当前元素时使用LinkList更高效。
Java - Time complexity of String.chartAt(i) ?。之前也找过了,就是O(1)。

你可能感兴趣的:(小练习,leetcode,java,算法)