文章目录
- 有效的括号
- 习题
- 我的解法
- 代码随想录解法
有效的括号
本节对应代码随想录中:代码随想录,对应视频链接为:栈的拿手好戏!| LeetCode:20. 有效的括号_哔哩哔哩_bilibili
习题
题目链接:20. 有效的括号 - 力扣(LeetCode)
给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号。
示例 2:
输入:s = "()[]{}"
输出:true
示例 3:
输入:s = "(]"
输出:false
我的解法
首先,如果字符串的位数为奇数,那一定不能全部配对。括号匹配问题,如果学过数据结构就知道这是典型的用栈来解决的问题。
遍历字符串,当前元素若和栈顶元素配成一对,那就弹出栈顶元素。如果最后栈为空,说明全部匹配,若不为空,则不能全部匹配。
问题在于一对括号,如"(“与”)",这两个是不相等的元素。没法简单的直接用相等判断一对括号。
但是观察三对括号的 ASCII 会发现:()分别为40和41;{}分别为123和125、[]分别为91和93。相信你已经看出规律了,右边的数值要比左边的大1或者大2,这样就可以用差值来判断是否为一对
注意题目中明确说了字符串只含有那三对括号中的元素,因此可以用差值来判断
class Solution {public:bool isValid(string s) {if (s.size() % 2 != 0) {return false;}stack<int> myStack;for (int i = 0; i < s.size(); i++) {int tmp = myStack.empty() ? 0 : s[i] - myStack.top();// 差值为1或者为2说明为一对if (tmp == 1 || tmp == 2) {myStack.pop(); // 弹出来栈中已匹配的左符号} else {myStack.push(s[i]); // 不匹配则push当前元素}}return myStack.empty();}
};
- 时间复杂度:O( n n n)。其中 n 是字符串 s 的长度
- 空间复杂度:O( n n n)。需要使用一个栈存储字符串的元素,其中 n 是字符串 s 的长度
代码随想录解法
我的解法中是用差值来判断是否为一对,而代码随想录是用多个 if 来判断各种情况。相比而言,我的代码更加简洁,不用写很多个 if 判断多种情况,但是代码随想录的效率更加高一点。原因在于我的解法必须遍历完全部元素才能返回结果,而代码随想录在遍历的过程中就可能得到结果。
具体来说,每次遇到左括号,将对应的右括号入栈。这样之后遇到遇到右括号就可以判断栈顶的元素是否等于当前右括号进行判断,如果不等或者栈已经空了,则返回 false。
class Solution {
public:bool isValid(string s) {if (s.size() % 2 != 0) return false; // 如果s的长度为奇数,一定不符合要求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(']');// 第三种情况:遍历字符串匹配的过程中,栈已经为空了,没有匹配的字符了,说明右括号没有找到对应的左括号 return false// 第二种情况:遍历字符串匹配的过程中,发现栈里没有我们要匹配的字符。所以return falseelse if (st.empty() || st.top() != s[i]) return false;else st.pop(); // st.top() 与 s[i]相等,栈弹出元素}// 第一种情况:此时我们已经遍历完了字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配,所以return false,否则就return truereturn st.empty();}
};
- 时间复杂度:O( n n n)。其中 n 是字符串 s 的长度
- 空间复杂度:O( n n n)。需要使用一个栈存储字符串的元素,其中 n 是字符串 s 的长度