有效的括号字符串
1、题目描述
给定一个字符串s,字符串s只包含以下三种完等:(,*,)
,请你判断s是不是一个合法的括号字符串。合法括号字符串有如下规则:
1.左括号(必须有对应的右括号)
2.右括号)必须有对应的左括号(
3.左括号必须在对应的右括号前面
4.*
可以视为单个左括号,也可以视为单个右括号,或者视为一个空字符
5.空字符串也视为合法的括号字符串。
数据范围:1\le s.length\le 100
输入1:
()()
输出1:
true
输入2:
(*)
输出2:
true
2、解题思路
使用两个栈,一个星号栈,一个左括号栈
1、然后遍历整个字符串
- 碰到左括号,入左括号栈
- 碰到星号,入星号栈
- 碰到右括号,优先在左括号栈出栈一个左括号与之匹配,若左括号栈为空,则在星号栈出栈一个
*
充当左括号与之匹配。 - 若碰到右括号且此时左括号栈和星号栈都为空,则直接返回
false
。
2、遍历完成之后,左括号栈和星号栈可能会有剩余,还需要判断
while (!leftStack.isEmpty() && !asterisStack.isEmpty())
,当左括号栈和星号栈都有剩余,那步骤如下:
- 左括号出栈(我们栈里面存的是左括号的下标)
- 右括号栈出栈(栈里面存的是星号的下标)
- 比较左括号下标和星号的下标(此时星号充当右括号),
if (leftIndex > asteriskIndex)
,则直接return false
。
3、在经历过上边两个步骤之后,若左括号栈还有剩余,直接返回false
,否则返回true
。
3、代码实现
public class LeetCode678 {
public static boolean checkValidString(String s) {
Deque<Integer> leftStack = new LinkedList<>(); //左括号栈
Deque<Integer> asterisStack = new LinkedList<>(); //星号栈
int n = s.length();
for (int i = 0; i < n; i++) {
char c = s.charAt(i);
if (c == '(') {
leftStack.push(i); //碰到左括号,入左括号栈
} else if (c == '*') { //碰到星号栈
asterisStack.push(i);
} else { //碰到右括号
if (!leftStack.isEmpty()) {//如果左括号不为空,左括号栈顶元素出栈
leftStack.pop();
} else if (!asterisStack.isEmpty()) { //如果左括号栈为空,则从星号栈出栈
asterisStack.pop();
} else { //左括号栈和星号栈都为空,这时候碰到了右括号,则直接返回false
return false;
}
}
}
//遍历完成之后,若左括号栈和星号栈都有剩余
while (!leftStack.isEmpty() && !asterisStack.isEmpty()) {
//左括号栈和星号栈的元素对应出栈
int leftIndex = leftStack.pop();
int asteriskIndex = asterisStack.pop();
//这个时候星号栈的元素就充当右括号,且右括号的下标必须大于左括号,否则直接false
if (leftIndex > asteriskIndex) {
return false;
}
}
//如果最后左括号栈为空,返回true,星号栈无所谓,因为可以当作空字符串对待
return leftStack.isEmpty();
}
public static void main(String[] args) {
System.out.println(checkValidString("()"));
System.out.println(checkValidString("(*)"));
System.out.println(checkValidString("(*))"));
System.out.println(checkValidString("()*))"));
}
}
本文作者: 别团等shy哥发育
版权声明: https://www.codeleader.top/ 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!