[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;
    }
}

猜你喜欢

转载自www.cnblogs.com/lz87/p/12723466.html
678
今日推荐