力扣日记:【栈与队列篇】有效的括号
日期:2023.10.25
参考:代码随想录、力扣
20. 有效的括号
题目描述
难度:简单
给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
左括号必须用相同类型的右括号闭合。
左括号必须以正确的顺序闭合。
每个右括号都有一个对应的相同类型的左括号。
示例 1:
输入:s = "()"
输出:true
示例 2:
输入:s = "()[]{}"
输出:true
示例 3:
输入:s = "(]"
输出:false
提示:
- 1 <= s.length <= 104
- s 仅由括号 ‘()[]{}’ 组成
题解
cpp ver
class Solution {
#define SOLUTION 2
public:
bool isValid(string s) {
#if SOLUTION == 1
// 对于([])这种情况,'[]'会先于'('出,即后进先出
// ([)] 是无效字符
if (s.size() == 0) {
return true;
}
stack<char> st;
st.push(s[0]);
for (int i = 1; i < s.size(); i++) {
if (!st.empty()) {
if (st.top() == '(') {
if (s[i] == ']' || s[i] == '}') {
return false;
} else if (s[i] == ')') {
st.pop();
} else {
st.push(s[i]);
}
} else if (st.top() == '[') {
if (s[i] == ')' || s[i] == '}') {
return false;
} else if (s[i] == ']') {
st.pop();
} else {
st.push(s[i]);
}
} else if (st.top() == '{') {
if (s[i] == ')' || s[i] == ']') {
return false;
} else if (s[i] == '}') {
st.pop();
} else {
st.push(s[i]);
}
}
} else {
if (s[i] == ')' || s[i] == ']' || s[i] == '}') {
return false;
} else {
st.push(s[i]);
}
}
}
if (st.empty()) {
return true;
}
return false;
#elif SOLUTION == 2 // 代码随想录版本
// 遇到 左括号时,将对应右括号加入栈
// 当遍历到 右括号时,再与栈顶的右括号匹配——如果相同则弹出(匹配成功);不同则非有效;栈空了也非有效
// 遍历完栈非空,也为无效字符串
// 如果s长度为奇数,一定不匹配
if (s.size() % 2 != 0) return false;
stack<char> st;
for (int i = 0; i < s.size(); i++) {
if (s[i] == '(') {
st.push(')');
} else if (s[i] == '{') {
st.push('}');
} else if (s[i] == '[') {
st.push(']');
} else if (!st.empty() && s[i] != st.top()) { // s[i]不是左括号,说明是右括号,则开始匹配
// 与栈顶元素不同,说明不匹配
return false;
} else if (st.empty()) { // 栈提前空了,说明右括号多余
return false;
} else { // 剩下情况即为st.top() 与 s[i]相等 //(!st.empty() && s[i] == st.top()) {
st.pop(); // 匹配成功,弹出
}
}
// 遍历完栈非空,也为无效字符串
return st.empty();
#endif
}
};
go ver
func isValid(s string) bool {
// s 长度为奇数
if len(s) % 2 != 0 {
return false
}
st := make([]byte, 0) // byte 类似于 字符类型
for i := 0; i < len(s); i++ {
if s[i] == '(' {
st = append(st, ')')
} else if s[i] == '[' {
st = append(st, ']')
} else if s[i] == '{' {
st = append(st, '}')
} else if len(st) > 0 && st[len(st) - 1] != s[i] {
return false
} else if len(st) == 0 {
return false
} else {
st = st[:len(st) - 1]
}
}
return len(st) == 0
}
复杂度
时间复杂度:O(n)
空间复杂度:O(n)
思路总结
- 栈由于其结构的特殊性,非常适合做对称匹配类题目
- 字符串里括号不匹配的几种情况
-
第一种情况:已经遍历完了字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配,所以return false
第二种情况:遍历字符串匹配的过程中,发现栈里没有要匹配的字符。所以return false
第三种情况:遍历字符串匹配的过程中,栈已经为空了,没有匹配的字符了,说明右括号没有找到对应的左括号return false
——By 代码随想录 - 代码随想录的解法思路:
- 遇到 左括号时,将对应右括号加入栈
- 当遍历到 右括号时,再与栈顶的右括号匹配——如果相同则弹出(匹配成功);不同则非有效;栈空了也非有效
- 遍历完栈非空,也为无效字符串
- 我的解法则类似于穷举,且在遇到左括号时直接将左括号放进来,导致在遇到右括号时需要有较复杂的类型判断,在写法上相对复杂