题目描述
//给定一个只包含三种字符的字符串:( ,) 和 ,写一个函数来检验这个字符串是否为有效字符串。有效字符串具有如下规则:
//
//
// 任何左括号 ( 必须有相应的右括号 )。
// 任何右括号 ) 必须有相应的左括号 ( 。
// 左括号 ( 必须在对应的右括号之前 )。
// * 可以被视为单个右括号 ) ,或单个左括号 ( ,或一个空字符串。
// 一个空字符串也被视为有效字符串。
//
//
// 示例 1:
//
//
//输入: “()”
//输出: True
//
//
// 示例 2:
//
//
//输入: "()"
//输出: True
//
//
// 示例 3:
//
//
//输入: “(*))”
//输出: True
//
主要思路
- 贪心地去掉所有的右括号
为什么是贪心呢?优先使用左括号匹配。只有当左括号没有的时候才使用星号去删除。 - 计算剩余的左括号及星号
((**符合
*(( 不符合。
基于上面分析,可以使用两个栈。一个用于存放“(",另外一个存放。
由于使用2个栈。因此栈里面存放的是index,而不是值。通过这种方式来知道相对顺序。
如果只使用一个栈也可以,只是要处理第一步贪心的地方。处理略显麻烦。
代码
public class P678ValidParenthesisString {
@Test
public void testP678ValidParenthesisString() {
Solution solution = new P678ValidParenthesisString().new Solution();
assertThat("1", solution.checkValidString("()"), CoreMatchers.is(true));
assertThat("1", solution.checkValidString("(*)"), CoreMatchers.is(true));
assertThat("1", solution.checkValidString("(*))"), CoreMatchers.is(true));
assertThat("1", solution.checkValidString("))***"), CoreMatchers.is(false));
}
//leetcode submit region begin(Prohibit modification and deletion)
class Solution {
public boolean checkValidString(String s) {
Deque<Integer> deque = new LinkedList<>();
Deque<Integer> assi = new LinkedList<>();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '(') {
deque.addLast(i);
} else if (c == ')') {
//优先使用左括号来消除
if (!deque.isEmpty()) {
deque.pollLast();
} else if (!assi.isEmpty()) {
//左括号用完的时候使用*.
assi.pollLast();
} else {
// 左括号、*都使用完了,说明此时只有右括号了,肯定匹配不上。直接返回。
return false;
}
} else {
assi.addLast(i);
}
}
// 走到这里说明右括号已经处理完了。处理其余的左括号与*
//((**这种情况是能够处理的。
while (!deque.isEmpty() && !assi.isEmpty()) {
// **((这种情况不不可能成功的,直接返回。
if (assi.pollLast() < deque.pollLast()) {
return false;
}
}
// 最后如果是(还有剩余。直接返回。
// 如果是*还有剩余,是符合要求的。
return deque.isEmpty();
}
}
//leetcode submit region end(Prohibit modification and deletion)
}