LeetCode集锦(六) - 第20题 Valid Parentheses

栏目: 编程工具 · 发布时间: 5年前

内容简介:本题思路很简单,如果左开符号(类似:(,{,[等),那么不管,或者把对应的压入栈,如果遇到右开,则需要判断离他最近的左开符号是否能成对,不能返回失败,如果能则需要去除,避免下一个判断的影响。 这边提供两类思路方案:方案一:不使用额外空间,只用当前数组,我们遇到右开符号,就要向前进行遍历,遇到第一个不为空的字符,判断是否能成对,如果能则继续,不能返回false。如果最终数组都是空字符串,那么符合要求,返回true,不然返回false。方案二:使用stack数据结构,把左开符号压入栈中,遇到右开符号,则拿出栈,
Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid. 

 An input string is valid if: 


 Open brackets must be closed by the same type of brackets. 
 Open brackets must be closed in the correct order. 


 Note that an empty string is also considered valid. 

Example 1: 
    Input: "()"
    Output: true

Example 2: 
    Input: "()[]{}"
    Output: true

Example 3: 
    Input: "(]"
    Output: false

Example 4: 
    Input: "([)]"
    Output: false

Example 5: 
    Input: "{[]}"
    Output: true
复制代码

翻译:

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

输入字符串在下列情况下有效:

  1. 开括号必须由相同类型的括号关闭。
  2. 开括号必须按正确的顺序关闭。
  3. 注意,空字符串也被认为是有效的。

示例1:

输入:“()”

输出:true

示例2:

输入:“()(){}”

输出:true

示例3:

输入:“()”

输出:false

示例4:

输入:“(())”

输出:false

例5:

输入:“{[]}”

输出:true

解题思路

本题思路很简单,如果左开符号(类似:(,{,[等),那么不管,或者把对应的压入栈,如果遇到右开,则需要判断离他最近的左开符号是否能成对,不能返回失败,如果能则需要去除,避免下一个判断的影响。 这边提供两类思路方案:

方案一:不使用额外空间,只用当前数组,我们遇到右开符号,就要向前进行遍历,遇到第一个不为空的字符,判断是否能成对,如果能则继续,不能返回false。如果最终数组都是空字符串,那么符合要求,返回true,不然返回false。

方案二:使用stack数据结构,把左开符号压入栈中,遇到右开符号,则拿出栈,pop一个,判断是否能成对,如果能则继续,不能返回false,如果最终栈是空的,返回true,否则返回false。

解题方法

  1. 第一种解体方法,按照我们的思路来编辑,代码如下

    public boolean isValid(String s) {
    
        char[] chars = s.toCharArray();
    
        for (int i = 0; i < chars.length; i++) {
            char indexItem = chars[i];
            char temp = ' ';
            switch (indexItem) {
                case ']':
                    temp = '[';
                    break;
                case '}':
                    temp = '{';
                    break;
                case ')':
                    temp = '(';
                    break;
                default:
                    temp = ' ';
            }
            if (temp != ' ' && !find(chars, i, temp)) {
                return false;
            }
        }
        return String.valueOf(chars).trim().length() == 0;
    }
    
    private boolean find(char[] chars, int lastIndex, char target) {
    
        for (int i = lastIndex - 1; i >= 0; i--) {
            char temp = chars[i];
            if (temp == ' ' || temp == ')' || temp == ']' || temp == '}') {
                continue;
            }
            if (chars[i] != target) {
                return false;
            }
            //两者滞空,
            chars[i] = ' ';
            chars[lastIndex] = ' ';
            return true;
        }
        return false;
    }
    复制代码

    时间复杂度: 该方案用了循环,循环层数为2(算上向前遍历),由于第二层判断计数不好记,设为M,外层循环为n,所以f(n)=(n*M)=Mn;所以O(f(n))=O(Mn),即T(n)=O(n^2)

    空间复杂度: 该方案没有使用额外的空间,所以空间复杂度是O(1);

  2. 第二种解题方法,按照我们的思路来编辑,代码如下

    Stack<Character> stack = new Stack<>();
        int size = s.length();
        for (int i = 0; i < size; i++) {
            char indexChar = s.charAt(i);
            switch (indexChar) {
                case '{':
                    stack.push('}');
                    break;
                case '[':
                    stack.push(']');
                    break;
                case '(':
                    stack.push(')');
                    break;
                default:
                    if (stack.size() == 0) {
                        return false;
                    } else if (stack.pop() != indexChar) {
                        return false;
                    }
            }
    
        }
        return stack.size() == 0;
    复制代码

    时间复杂度: 该方案用了循环,循环层数为1,循环为n,所以f(n)=(n)=n;所以O(f(n))=O(n),即T(n)=O(n)

    空间复杂度: 该方案使用栈作为额外,额外的空间最坏的情况就是全部入栈,为n,所以空间复杂度是O(n);

  3. 第三种解题方法,按照我们的思路来编辑,代码如下

    LinkedList<Character> linkedList=new LinkedList();
        int size = s.length();
        for (int i = 0; i < size; i++) {
            char indexChar = s.charAt(i);
            switch (indexChar) {
                case '{':
                    linkedList.addFirst('}');
                    break;
                case '[':
                    linkedList.addFirst(']');
                    break;
                case '(':
                    linkedList.addFirst(')');
                    break;
                default:
                    if (linkedList.size() == 0) {
                        return false;
                    } else if (linkedList.getFirst() != indexChar) {
                        return false;
                    }
                    linkedList.remove(0);
            }
    
        }
    
        return linkedList.size() == 0;
    复制代码

    时间复杂度: 该方案用了循环,循环层数为1,循环为n,所以f(n)=(n)=n;所以O(f(n))=O(n),即T(n)=O(n)

    空间复杂度: 该方案使用链表作为额外,额外的空间最坏的情况就是全部入链表,为n,所以空间复杂度是O(n);

总结

本题的大致解法如上所诉,本题两种思路,三种解题方式,第三种主要是选择的数据结构不同,java自带的Stack是继承Vector,是一个线程安全的,但是在本题不需要考虑安全性,所以加锁的开销是多余的,而且不能一开始就设置Stack的大小,在Vector中使用数组作为存储结构,所以当长度足够长,数组扩容时间和空间损耗会比较大,所以选用LinkedList,没有数组扩容的问题,可以随意增加和删除节点。没有必要线程安全,就没有加锁的额外开销了。


以上所述就是小编给大家介绍的《LeetCode集锦(六) - 第20题 Valid Parentheses》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

超级运营术

超级运营术

韩叙 / 中信出版社 / 2017-5

新产品上线,为什么仅仅500次转发能带来300个内测用户? 为什么每一次内容推送,都带来App的一次卸载高峰? 同类活动那么多,怎样做才能超越竞品,占据头条? 为什么有的文案像“小广告”,有的文案像贴心老友? 创业公司与大平台的玩法有何不同? …… 如何从“了解运营”到“精通运营”,可能是运营人*的困惑。《超级运营术》正是对这个问题的全面解答。韩叙总结10年运营......一起来看看 《超级运营术》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

在线进制转换器
在线进制转换器

各进制数互转换器

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具