文章目录
678. Valid Parenthesis String【stack+logic,greedy,dynamic】
Given a string s containing only three types of characters: ‘(’, ‘)’ and ‘*’, return true if s is valid.
The following rules define a valid string:
Any left parenthesis ‘(’ must have a corresponding right parenthesis ‘)’.
Any right parenthesis ‘)’ must have a corresponding left parenthesis ‘(’.
Left parenthesis ‘(’ must go before the corresponding right parenthesis ‘)’.
‘*’ could be treated as a single right parenthesis ‘)’ or a single left parenthesis ‘(’ or an empty string “”.
Example 1:
Input: s = “()”
Output: true
Example 2:
Input: s = “(*)”
Output: true
Example 3:
Input: s = “(*))”
Output: true
Constraints:
1 <= s.length <= 100
s[i] is ‘(’, ‘)’ or ‘*’.
stack O(n)
class Solution {
public:
bool checkValidString(string s) {
int n=s.size();
vector<int>starSum(n,0);
stack<int> myStack;
deque<int> myStar;
int now=0;
for(int i=0;i<n;i++){
if(s[i]=='*')myStar.push_back(i);
else if(s[i]=='('){
myStack.push(i);
}else{
if(!myStack.empty())myStack.pop();
else if(!myStar.empty()){
myStar.pop_front();
}else {
return false;
}
}
}
while(!myStack.empty()){
int index=myStack.top();
myStack.pop();
if(myStar.empty())return false;
int sindex=myStar.back();;
if(sindex>index){
myStar.pop_back();
}else{
return false;
}
}
return true;
}
};
- just attend logic and data structure
- and greedy:a right parenthesis must match a left parenthesis or star, and choose the leftmost, because the rightmost maybe need to save for the left parenthesis
- so the rest left parenthesis must match a left parenthesis or star, and choose the rightmost
- actually, just all stack is OK, because when the right parenthesis match the star, no left parenthesis in left
dynamic O(n^2)
class Solution {
public boolean checkValidString(String s) {
int n = s.length();
boolean[][] f = new boolean[n + 1][n + 1];
f[0][0] = true;
for (int i = 1; i <= n; i++) {
char c = s.charAt(i - 1);
for (int j = 0; j <= i; j++) {
if (c == '(') {
if (j - 1 >= 0) f[i][j] = f[i - 1][j - 1];
} else if (c == ')') {
if (j + 1 <= i) f[i][j] = f[i - 1][j + 1];
} else {
f[i][j] = f[i - 1][j];
if (j - 1 >= 0) f[i][j] |= f[i - 1][j - 1];
if (j + 1 <= i) f[i][j] |= f[i - 1][j + 1];
}
}
}
return f[n][0];
}
}
作者:AC_OIer
链接:https://leetcode-cn.com/problems/valid-parenthesis-string/solution/gong-shui-san-xie-yi-ti-shuang-jie-dong-801rq/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
定义 f[i][j] 为考虑前 i 个字符(字符下标从 1 开始),能否与 j 个右括号形成合法括号序列。
Greedy O(n)
class Solution {
public boolean checkValidString(String s) {
int l = 0, r = 0;
for (char c : s.toCharArray()) {
if (c == '(') {
l++; r++;
} else if (c == ')') {
l--; r--;
} else {
l--; r++;
}
l = Math.max(l, 0);
if (l > r) return false;
}
return l == 0;
}
}
作者:AC_OIer
链接:https://leetcode-cn.com/problems/valid-parenthesis-string/solution/gong-shui-san-xie-yi-ti-shuang-jie-dong-801rq/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
由于存在可变化的 * 符号,因此考虑在考虑前 i 个字符,其能与消耗的左括号的数量具有明确的「上界与下界」。且当前上界与下界的变化,仅取决于「当前为何种字符」,以及「处理上一个字符时上界与下界为多少」
需要注意的是,在匹配过程中如果 l 为负数,需要重置为 0,因为如果当前序列本身为不合法括号序列的话,增加 ( 必然还是不合法。同时,当出现 l > r 说明上界为负数,即右括号过多,必然为非合法方案,返回 falsefalse。
作者:AC_OIer
链接:https://leetcode-cn.com/problems/valid-parenthesis-string/solution/gong-shui-san-xie-yi-ti-shuang-jie-dong-801rq/
class Solution {
public boolean checkValidString(String s) {
int l=0,r=0;
for(int i=0;i<s.length();i++){
char c=s.charAt(i);
if(c=='('){
l++;r++;
}else if(c==')'){
l--;r--;
}else{
l--;r++;
}
if(l<0)l=0;
if(r<0)return false; //!!!!
}
return l==0;
}
}
deque c++
deque双端队列的操作(可以在队头队尾进行入队出队操作)
deque<int> dq;创建一个数双端队列dq
dq.empty();判断队列是否为空,为空返回true
dq.push_front(s);将s从队头入队
dq.push_back(s);将s从队尾入队,和普通队列方式一样
dq.front();只返回队头元素
dq.back();只返回队尾元素
dq.pop_front();将队头元素弹出
dq.pop_back;将队尾元素弹出
dq.clear();将队列清空