场景:
1、题目:
给定一个只包括 ‘(’,’)’,’{’,’}’,’[’,’]’ 的字符串 s ,判断字符串是否有效。
2、满足条件:
(1)左括号必须用相同类型的右括号闭合;
(2)左括号必须以正确的顺序闭合;
3、示例输出
示例 1:
输入:s = “()”
输出:true
示例 2:
输入:s = “()[]{}”
输出:true
示例 4:
输入:s = “([)]”
输出:false
4、提示
(1)1 <= s.length <= 104;
(2)s 仅由括号 ‘()[]{}’ 组成;
(3)s.length 是奇数或偶数;
思路:
(1)若字符串的长度是奇数,必然不符合 “有效的括号“ 的定义,直接返回 false;
(2)使用 unordered_map 容器将对应的括号以键值对的形式存储;
(3)官方思路:
遍历给定的字符串 s,当遇到一个左括号时,期望在后续遍历中,有一个相同类型的右括号将其闭合。
由于栈的特性,所以先遇到的左括号要后闭合,因此将这个左括号放入栈顶。当之后遇到这个相同类型的右括号时,就需要一个相同类型的左括号将其闭合。
此时,取出栈顶的左括号并判断与刚才遇到的这个右括号是否是相同类型的括号。如果不是相同的类型,或者栈中并没有左括号,那么字符串 s 无效,返回 False。
为了快速判断括号的类型,我们可以使用哈希表存储每一种括号。哈希表的键为右括号,值为相同类型的左括号。
在遍历结束后,如果栈中没有左括号,说明我们将字符串 s 中的所有左括号闭合,返回 True,否则返回 False。
扩展:
一、哈希(无序关联式容器)
(1)map 容器中存储的数据是有序的,unordered_map容器中存储的数据是无序的,本质原因是unordered_map 容器底部采用的是哈希表存储结构,该结构本身不具有对数据的排序功能;
(2)以键值对(pair 类型)的形式存储数据,存储的各键值对互不相同且不允许被修改;
(3)unordered_map()有 5 个参数,这里我们只需要前两个参数 key、T,分别代表键、值;
(4)常见创建 unordered_map 容器的方式有 4 种,这里我们只介绍默认构造函数,创建时可以直接完成初始化操作,详见代码;
二、栈(线性存储结构)
(1)存储逻辑关系为 ”一对一“ 数据的线性存储结构;
(2)栈只能从一段存取数据,另一端是封闭的,栈的开口端称为栈顶,封口端称为栈底;
(3)栈中存取数据都遵循 ”先进后出“的原则;
(4)栈是一种特殊的线性结构,具体实现有顺序存储结构和链式存储结构两种,这里我们采用顺序栈;
代码实现:
#include <string>
#include <unordered_map>
#include <stack>
using namespace std;
// 官方版
class Solution
{
public:
bool isValid(string s)
{
// 判断 s 的长度是奇数还是偶数
int n = s.length();
if (n % 2 == 1)
{
return false;
}
// 无序哈希
unordered_map<char, char> pairs =
{{')', '('},
{']', '['},
{'}', '{'}};
// 栈
stack<char> stk;
// 遍历 s
for (char ch : s)
{
if (pairs.count(ch))
{
if (stk.empty() || stk.top() != pairs[ch])
{
return false;
}
// 返回并删除栈顶元素
stk.pop();
}
else
{
// 向栈中添加元素
stk.push(ch);
}
}
//
return stk.empty(); // 若 stack 为空 返回 true
}
};