20. 有效的括号 - 力扣(LeetCode)https://leetcode.cn/problems/valid-parentheses/
题目
给定一个只包括 '('
,')'
,'{'
,'}'
,'['
,']'
的字符串 s
,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 每个右括号都有一个对应的相同类型的左括号。
示例 1:
输入:s = "()" 输出:true
示例 2:
输入:s = "()[]{}" 输出:true
示例 3:
输入:s = "(]" 输出:false
提示:
1 <= s.length <= 104
s
仅由括号'()[]{}'
组成
图解
代码(思路都在代码中)
typedef char STDataType;
// 栈的结构
typedef struct Stack {
STDataType* a; // 指针
int top; // 栈顶
int capacity; // 容量
} Stack;
// 扩容函数
void Exp(Stack* p) {
if (p->capacity == p->top) {
// 利用三目运算来判断是否
int New_cap = p->capacity == 0 ? 4 : p->capacity * 2;
STDataType* tmp =
(STDataType*)realloc(p->a, New_cap * sizeof(STDataType));
if (tmp == NULL) {
assert("realloc");
return;
}
// 将开辟空间给给原来的变量
p->a = tmp;
p->capacity = New_cap;
}
}
// 初始化
void StackInit(Stack* p) {
assert(p);
p->a = NULL;
p->capacity = p->top = 0;
}
// 入栈
void StackPush(Stack* p, STDataType data) {
assert(p);
// 判断空间
Exp(p);
// 入栈
p->a[p->top] = data;
// 入栈后栈顶向上移动
p->top++;
}
// 出栈
void StackPop(Stack* p) {
assert(p);
assert(p->top > 0); // 确保不为空
// 判断是否元素是否为0,避免越界
/*if (p->top == 0)
{
return;
}*/
p->top--;
}
// 获取栈顶元素
STDataType StackTop(Stack* p) {
// 判断是否为0
if (p->top == 0) {
return (STDataType)0; // 由于返回类型是 STDataType,所以需要强制转换
}
return p->a[p->top - 1];
}
// 获取栈中有效元素个数
int StackSize(Stack* p) { return p->top; }
// 判空
bool StackEmpty(Stack* p) {
// 使用逻辑非操作符(!)来检查栈顶指针(top)是否为0(即栈是否为空)
// 如果top为0,说明栈中没有任何元素,因此栈是空的
// 在C语言中,逻辑非操作符会将0转换为1(true),非0转换为0(false)
// 所以当栈顶指针top为0时,!p->top的结果为true(非零值),表示栈为空
// 反之,如果栈中有元素(top非0),则!p->top的结果为false(0),表示栈非空
return !p->top;
}
// 销毁栈
void StackDestroy(Stack* p) {
if (p->a) {
free(p->a);
p->a = NULL;
p->capacity = p->top = 0;
}
}
bool isValid(char* s) {
// 思路:我们利用栈来解决这个问题,利用进先出的特性
// 创建栈
Stack s1;
// 初始化栈
StackInit(&s1);
// 利用循环来遍历字符
while (*s) {
// 让左括号入栈
if (*s == '(' || *s == '{' || *s == '[' ) {
StackPush(&s1, *s);
} else { // 右括号取栈顶的左括号匹配
// 首先我们判断是否为空
if (StackEmpty(&s1)) { // 这里说明栈我为空(也就是说左括号没有和右括号对应或者说就只有一个右括号)
StackDestroy(&s1); // 直接释放栈
return false;
}
// 获取栈顶元素(这里就有了后进先出的原理了)
STDataType top = StackTop(&s1);
// 获取后出栈,方便下一次入栈
StackPop(&s1);
// 判断是否对应(这边判断的条件是不相等,这样就可以排除所有可能false)
if ((top == '{' && *s != '}')||(top == '[' && *s != ']')||(top == '(' && *s != ')'))
// 也就是说:栈里面的左括号&&字符中不等于和他对应的右括号
{
return false;
StackDestroy(&s1);
}
}
++s; // 每次遍历向后移动
}
// 循环跳出就意味着排除了这些可能,但是这边我们不排除只有一个左括号或者右括号或者左括号比右括号多,所以需要判空
bool ret = StackEmpty(&s1);
StackDestroy(&s1); // 这边我们需要释放一下,避免空间泄露
return ret;
}