手撕leetcode第20题之有效括号

喜欢而已 提交于 2019-12-17 04:21:07

题目

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

有效字符串需满足:

左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。

示例 1:

输入: “()”
输出: true
示例 2:

输入: “()[]{}”
输出: true
示例 3:

输入: “(]”
输出: false
示例 4:

输入: “([)]”
输出: false
示例 5:

输入: “{[]}”
输出: true

分析

首先审题,字符串只包含开括号或者闭括号,判断括号是否有效。其实这道题很好想到采用栈来解决,遇到开括号入栈,闭括号取出栈顶的开括号比较与闭括号是否同一类型。如果是同一类型弹出栈顶的开括号,遍历完字符串后,如果栈为空,则证明字符串为有效字符串。
在这里插入图片描述

代码实现

/**
     * 判断有效字符串 时间复杂度是O(n) 空间复杂度O(m)
     * @param s
     * @return
     */
    private boolean isValid(String s){

        if ("".equals(s)){
            return true;
        }

        Stack<Character> stack = new Stack<>();
        int length = s.length();
        for (int i = 0; i < length; i++) {
            if (s.charAt(i) == '(' || s.charAt(i) == '[' || s.charAt(i) == '{'){
                // 左括号进栈
                stack.push(s.charAt(i));
            }else {
                if (stack.empty()){
                    // 是右括号先出现
                    return false;
                }else {
                    // 出现右括号
                    String str = stack.peek() +""+ s.charAt(i);
                    if (str.equals("()") || str.equals("{}") || str.equals("[]")){
                        stack.pop();
                    }else {
                        return  false;
                    }
                }
            }
        }
        if (stack.empty()){
            return true;
        }
        return false;
    }
提交结果

在这里插入图片描述

性能分析

看着提交报告就应该知道这个方案的性能不是很好,分析下时间复杂度是O(n),n是字符串的长度,空间复杂度是O(m),m是最长有效字符串的长度的一半,其实从这个算法的复杂度上我觉得已经没有什么可以优化的了,但是代码确实有点冗余,比如判断闭括号的那段逻辑,我觉得无论是对时间复杂度还是空间复杂度都是有一定的影响的,所以优化如下的方案。

优化后的代码
/**
     * 判断有效字符串 时间复杂度是O(n) 空间复杂度O(m)
     * @param s
     * @return
     */
    private boolean isValid2(String s){

        if ("".equals(s)){
            return true;
        }

        Stack<Character> stack = new Stack<>();
        int length = s.length();
        for (int i = 0; i < length; i++) {
            if (s.charAt(i) == '(' || s.charAt(i) == '[' || s.charAt(i) == '{'){
                // 左括号进栈
                stack.push(s.charAt(i));
            }else {
                if (stack.empty()){
                    // 是右括号先出现
                    return false;
                }else {
                    // 出现右括号 判断栈顶元素与当前元素是否是同一类型的括号
                    if ((stack.peek() == '(' && s.charAt(i) == ')')
                            || (stack.peek() == '[' && s.charAt(i) == ']')
                            || (stack.peek() == '{' && s.charAt(i) == '}')){
                        stack.pop();
                    }else {
                        return  false;
                    }
                }
            }
        }
        if (stack.empty()){
            return true;
        }
        return false;
    }
再次提交

在这里插入图片描述

性能分析

这次代码的执行用时和内存消耗都提升了一倍的性能,但是其实改的代码也就是闭括号逻辑判断的处理。

总结

这道题是一道很简单的题,但是考查的点其实是挺好的,是一个经典的栈的使用,上一篇算法的题里,我就提到了算法讲究的是思维方式的拓展,可以先窥探他人的思维方式,然后再培养自己的思维方式,最后想提的是,优化代码不仅仅是算法的改进,也可以是代码的优化,我们今天这道题两种方法的算法逻辑是一样的,但是优雅了代码的写法就提升了近一倍的性能,所以大家在写代码时还是要尽量优雅。

扫码关注公众号

在这里插入图片描述

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!