• [LeetCode 678] Valid Parenthesis String


    Given a string containing only three types of characters: '(', ')' and '*', write a function to check whether this string is valid. We define the validity of a string by these rules:

    1. Any left parenthesis '(' must have a corresponding right parenthesis ')'.
    2. Any right parenthesis ')' must have a corresponding left parenthesis '('.
    3. Left parenthesis '(' must go before the corresponding right parenthesis ')'.
    4. '*' could be treated as a single right parenthesis ')' or a single left parenthesis '(' or an empty string.
    5. An empty string is also valid.

     

    Example 1:

    Input: "()"
    Output: True
    

     

    Example 2:

    Input: "(*)"
    Output: True
    

     

    Example 3:

    Input: "(*))"
    Output: True
    

     

    Note:

    1. The string size will be in the range [1, 100].

    One way of solving this is to simulate a run through of s.

    1. each time we see a (,  push it to a stack;

    2. if we see a *, add to the end of a deque;

    3. if we see a ), we first try to use the last appearing ( to match. If there is no (, we then try to use the first appearing * to match. If we can do neither, return false.

    4. after going through the entire s, we've matched all ) with ( or *. Now we need to match all remaining unmatched (. To achieve this, we must have enough * that each of these matching * is to the right of its matching (.  For example,  ***(((, even if we have enough *, but due to the relative position, we can't match. On the other hand, we can match (*(*(* 

    This requires comparing the stack top and the dqeue end one by one.

    The runtime is O(N) and space is O(N).

    class Solution {
        public boolean checkValidString(String s) {
            Stack<Integer> stack = new Stack<>();
            ArrayDeque<Integer> wild = new ArrayDeque<>();
            for(int i = 0; i < s.length(); i++) {
                if(s.charAt(i) == '(') {
                    stack.push(i);
                }
                else if(s.charAt(i) == ')') {
                    if(stack.size() > 0) {
                        stack.pop();
                    }
                    else if(wild.size() > 0) {
                        wild.pollFirst();
                    }
                    else {
                        return false;
                    }
                }
                else {
                    wild.addLast(i);
                }
            }
            while(stack.size() > 0) {
                if(wild.size() == 0 || wild.pollLast() < stack.pop()) {
                    return false;
                }
            }
            return true;
        }
    }

    Can we solve this problem with only O(1) space? The answer is yes.

    If we keep a difference count between ( and ), because we have * that can be used as (, ), or empty space, this diff count has a range of values, depending on how * is used. Let's denote this range as [minDiff,  maxDiff] where minDiff represents every * is interpreted as ) and maxDiff represents every * is interpreted as (. 

    if (,  minDiff++, maxDiff++;

    if ), minDiff--, maxDiff--;

    if *, maxDiff++, minDiff--; 

    If at any point, maxDiff is < 0, it is impossible to do a match because we don't have enough ( or * to match ). 

    If at any point, minDiff is < 0, we need to reset it to 0. Why? Because it is useless to have unmatched ) to the left of ( or * as we can not do a match like )( or )* anyway. So resetting to 0 represents that we ignore impossible cases like this.

    Check minDiff after going through s to make sure it is 0. If not, we know we do not have enough ) or * to match all (. 

    O(N) runtime, O(1) space

    class Solution {
        public boolean checkValidString(String s) {
            int minDiff = 0, maxDiff = 0;
            for(int i = 0; i < s.length(); i++) {
                switch(s.charAt(i)) {
                    case '(':
                        maxDiff++;
                        minDiff++;
                        break;
                    case ')':
                        maxDiff--;
                        minDiff--;
                        break;
                    case '*':
                        maxDiff++;
                        minDiff--;
                        break;
                }
                if(maxDiff < 0) {
                    return false;
                }
                minDiff = Math.max(0, minDiff);
            }
            return minDiff == 0;
        }
    }
  • 相关阅读:
    Django动态渲染多层菜单
    python使用pdkdf2加盐密码
    ceil 模块
    python面试总结
    Django 中related_name,"%(app_label)s_%(class)s_related"
    安装zabbix-3.0.3+nginx-1.10.1+php-5.6.22
    Django 权限管理
    python RecursionError: maximum recursion depth exceeded in comparison错误
    django _meta方法
    html 之input标签height设置问题
  • 原文地址:https://www.cnblogs.com/lz87/p/12723466.html
Copyright © 2020-2023  润新知