给定一个只包含三种字符的字符串:( ,) 和 *,写一个函数来检验这个字符串是否为有效字符串。有效字符串具有如下规则:
1.任何左括号 ( 必须有相应的右括号 )。
2.任何右括号 ) 必须有相应的左括号 ( 。
3.左括号 ( 必须在对应的右括号之前 )。
4.* 可以被视为单个右括号 ) ,或单个左括号 ( ,或一个空字符串。
5.一个空字符串也被视为有效字符串。
解答:
1、使用两个栈分别存储左括号和星号的下标,leftBracketStack和starStack。遇到右括号,优先与左括号栈顶抵消,若左括号为空,才与星栈顶抵消。
2、最后若leftBracketStack和starStack不为空,再进行处理。如果左括号栈顶大于星栈顶,类似*(,则无法抵消,返回false;如果左括号栈顶小于星栈顶,类似(*,则可以抵消,同时弹出栈顶。往下处理知道其中一个(两个)为空
3、最后若leftBracketStack不为空,starStack为空,没有多余的星号与左括号进行匹配,返回false。否则返回true。
public boolean checkValidString(String s) { if (s == null || s.length() == 0) { return true; } Stack<Integer> leftBracketStack = new Stack<>(); Stack<Integer> starStack = new Stack<>(); for (int i = 0; i < s.length(); ++i) { char ch = s.charAt(i); if (ch == '(') { leftBracketStack.push(i); } else if (ch == '*') { starStack.push(i); } else { if (leftBracketStack.isEmpty() && starStack.isEmpty()) { return false; } else if (!leftBracketStack.isEmpty()) { // 优先匹配左括号 leftBracketStack.pop(); } else { // 没有左括号才去匹配星号 starStack.pop(); } } } // 处理剩余的左括号和星号。从后往前,从栈顶开始处理 while (!leftBracketStack.isEmpty() && !starStack.isEmpty()) { if (leftBracketStack.peek() > starStack.peek()) { // 左括号在星号后面,比如*(,不符合 return false; } // 否则左括号在星号前面,比如(*,符合,弹出继续向前匹配 leftBracketStack.pop(); starStack.pop(); } if (!leftBracketStack.isEmpty()) { // 最后剩余左括号,不符合 return false; } return true; }