ValidParentheses [source code]


public class ValidParentheses {
static
/******************************************************************************/
public class Solution {
    public boolean isValid(String s) {
        if (s.length() == 0 || s.length() % 2 != 0) return false;
        char[] chs = s.toCharArray();
        char[] map = new char[256];
        map[')'] = '(';
        map[']'] = '[';
        map['}'] = '{';
        Stack<Character> stack = new Stack<>();
        for (int i = 0; i < chs.length; i++) {
            if (map[chs[i]] == 0) {
                stack.push(chs[i]);
            } else {
                if (stack.empty() || stack.peek() != map[chs[i]]) return false;
                stack.pop();
            }
        }
        return stack.empty();
    }
}
/******************************************************************************/

    public static void main(String[] args) {
        ValidParentheses.Solution tester = new ValidParentheses.Solution();
        String[] inputs = {
            "()", //true
            "()[]{}", //true
            "([)]", //false
            "([])", //true
            "((", //false
        };
        for (String s : inputs) System.out.println(s + " -> " + tester.isValid(s));
    }
}

其实是一个非常简单的问题, 不过我对 Stack 不太熟悉, 所以还是花了太多的时间; 最后的速度是11ms (40%), 不算快. 当然这个题目想要加速的话, 其实也是很简单的, 比如这里的 Stack 可以用一个 array 来做. 不过暂时就不搞这种 trivial 的 optimization了. //稍微改了一下, 有8(92)了, 不知道什么情况;

看了一下, submission 上面最快的几个, 果然都是直接用 array 来做 Stack 的, 看看就行了, 如果以后有时间, 自己再来实现, 现在不纠结这种小细节;

stream 算法的末尾处理

这个吃亏不是一回两回了, 这一题我想到了开头的地方要有特殊的检查(stack 还是空的时候, 就直接来一个右括号), 但是没有想到末尾的检查. 这个就是左括号太多的情况, 也要考虑, 这个只要在stream end加一个检查就行了;


这个是 discussion 最优解:

public boolean isValid(String s) {  
    Stack<Character> stack = new Stack<Character>();  
    for (char c : s.toCharArray()) {  
        if (c == '(')  
            stack.push(')');  
        else if (c == '{')  
            stack.push('}');  
        else if (c == '[')  
            stack.push(']');  
        else if (stack.isEmpty() || stack.pop() != c)  
            return false;  
    }  
    return stack.isEmpty();  
}

思路其实都是一样的, 不过他这个简练很多. 我这里刚开始的做一个hash array 之类的这个操作其实并没有什么实际的必要, 因为这里的 可能性太少了;

反正这题一个稍微值得注意的优化点就是不能来左括号你就 push 左括号, 而应该 push 右括号, 这样后面查询的代码可以统一成一个 branch(因为不用考虑不同的 literal 了);

以前还讲过用 string 来做 Map 的思路, 这里是一个版本:

public class Solution {  
    public boolean isValid(String s) {  
        Stack<Integer> p = new Stack<>();  
        for(int i = 0; i < s.length(); i++) {  
            int q = "(){}[]".indexOf(s.substring(i, i + 1));  
            if(q % 2 == 1) {  
                if(p.isEmpty() || p.pop() != q - 1) return false;  
            } else p.push(q);  
        }  
        return p.isEmpty();  
    }  
}

大概看看就行, 也是比较蛋疼的东西; 除了简化代码以外一无是处;

这个是一个更加奇葩的 string-based 的答案:

public class Solution {  
    public boolean isValid(String s) {  
        int length;  

        do {  
            length = s.length();  
            s = s.replace("()", "").replace("{}", "").replace("[]", "");  
        } while(length != s.length());  

        return s.length() == 0;  
    }  
}

而且这个代码的速度估计还不会很好;

下面的人对这个代码的意见:
Nooooo! Stop upvoting it....

In an algorithms coding community who appreciates constructing 3*n/2 separate String objects to validate a single String? Not to mention that each replace call uses regex:

  • compiles a Pattern
  • creates a Matcher
  • builds the replacement using a StringBuffer ("synchronized StringBuilder")
    Don't get me wrong, regex is awesome, I love it, and use it very often for parsing complex structures. The difference is that for some tasks there are faster ways. Just because a code has less characters it doesn't mean it's better. My outburst is highly correlated to using a regex without knowing it or knowingly in a loop that isn't pre-compiled. Consider the following code:
public class Solution {  
    private static final Pattern PARENS = Pattern.compile("\\(\\)|\\[\\]|\\{\\}");  
    public boolean isValid(String s) {  
        int length;  
        do {  
            length = s.length();  
            s = PARENS.matcher(s).replaceAll("");  
        } while (length != s.length());  
        return s.isEmpty();  
    }  
}

same result, 1 regex = 1 compile overall, 1 extra string created per iteration; still using StringBuffer though. I would be happier with this, but there's still a way to do it by iterating over the characters of the input once.

意思是这个代码其实速度比你想象的还要糟糕的多;


Problem Description

Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid.

The brackets must close in the correct order, "()" and "()[]{}" are all valid but "(]" and "([)]" are not.

Difficulty:Easy
Total Accepted:210.1K
Total Submissions:632K
Contributor: LeetCode
Companies
google airbnb facebook twitter zenefits amazon microsoft bloomberg
Related Topics
stack string
Similar Questions
Generate Parentheses Longest Valid Parentheses Remove Invalid Parentheses

results matching ""

    No results matching ""