给定一个只包含三种字符的字符串:( ,) 和 *,写一个函数来检验这个字符串是否为有效字符串。有效字符串具有如下规则:
1、任何左括号 ( 必须有相应的右括号 )。
2、任何右括号 ) 必须有相应的左括号 ( 。
3、左括号 ( 必须在对应的右括号之前 )。
4、* 可以被视为单个右括号 ) ,或单个左括号 ( ,或一个空字符串。
5、一个空字符串也被视为有效字符串。
示例 1:
输入: "()"
输出: True
示例 2:
输入: "(*)"
输出: True
示例 3:
输入: "(*))"
输出: True
这个题目和之前的这个题非常相似,可以参考我这个算法解题:
https://blog.csdn.net/aa5305123/article/details/82217570
这道理的解题思路,看代码注释,一眼万里,清晰明了,世上最人性的注释。
public class ValidParenthesisString {
//和之前的这个题非常相似ValidParentheses
public static boolean checkValidString(String s) {
//同样我们利用栈存储,因为只有一种括号-小括号,我们不需要用hashMap 存放左右括号了,code直接判断就行
//但是,这里需要注意,*(这个情况,他不是有效括号。
//基于这个问题,我们的栈,就不能单纯的存字符括号和*号了,必须存放索引,当遍历完后,我们需要比较索引
//解题思路,就是遍历字符数组,遇到左括号,左括号索引放入左括号栈,遇到*号,索引放入star栈。
//当遇到右括号的时候,这就先优先从左括号出栈,如果左括号栈空了,再从star栈出栈
Stack<Integer> leftParenthesis = new Stack<>();//用来存放左括号
Stack<Integer> starParenthesis = new Stack<>();//用来存放星号
char[] arr = s.toCharArray();
for (int a = 0; a < arr.length; a++) {
if (arr[a] == '(') {//左括号
leftParenthesis.push(a);//左括号的索引入栈
} else if (arr[a] == '*') {//星号
starParenthesis.push(a);//星号的索引入栈
} else {//右括号
if (!leftParenthesis.isEmpty()) {//左括号栈有存货
leftParenthesis.pop();
} else {//左括号空了,开始从star栈找
if (starParenthesis.isEmpty()) {//如果*栈也空了,直接返回false
return false;
} else {
starParenthesis.pop();//*号栈必须出栈了,代表左括号
}
}
}
}
//遍历完字符数组后,需要判断左括号栈,和*栈了。针对*(这中情况,左括号在*号的右边
while (!leftParenthesis.isEmpty() && !starParenthesis.isEmpty()) {
if (leftParenthesis.peek() > starParenthesis.peek()) {
return false;
}
leftParenthesis.pop();
starParenthesis.pop();
}
//最后只需要判断左括号是否有剩余。毕竟最后如果剩下的都是***,那都是有效括号空字符
return leftParenthesis.isEmpty();
}
public static void main(String[] args) {
System.out.println(checkValidString("(*()"));
}
}