有关这道力扣上的题,通过反复思考和资料查询,为大家总结出了这三种解法,分别是暴力解法、分支判断以及哈希表,在LeetCode上都可以AC
力扣题目链接
给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串 s ,判断字符串是否有效。
有效字符串需满足:
1、左括号必须用相同类型的右括号闭合。
2、左括号必须以正确的顺序闭合。
示例1
输入: “()”
输出: true
示例2
输入:s = “()[]{}”
输出:true
示例3
输入:s = “(]”
输出:false
示例4
输入:s = “([)]”
输出:false
示例5
输入:s = “{[]}”
输出:true
class Solution {
public:
bool isValid(string s) {
stack<char> t;
for(int i=0;i<s.size();++i)
{
if(t.empty())
{
t.push(s[i]);
continue;
}
char m_top=t.top();
if(s[i]=='}' && m_top=='{')
{
t.pop();
continue;
}
else if(s[i]==']' && m_top=='[')
{
t.pop();
continue;
}
else if(s[i]==')' && m_top=='(')
{
t.pop();
continue;
}
t.push(s[i]);
}
return t.empty();
}
};
代码千万条,暴力第一条;暴力不规范,编译两行泪
虽然有时候暴力解法还是挺管用的,一个个列出所要求的情况,但是这样所带来的便是时间复杂度的提升,有时候直接上两层for循环就是O(n2)的复杂度,还有一个就是暴力很容易导致超时,用过暴力刷题的小伙伴都清楚,所以我们还是尽量避免用暴力,尽量想出一些最优解,实在想不出来才用暴力。下面两种是我想出来的其他两种方案,大家可以仔细看看;
首先,来分析一下三种不同的情况
第一种 匹配结束,仍有括号剩余没有匹配(已进栈),因此栈不为空
第二种 在匹配过程中,发现无与之匹配的前括号
第三种 在匹配过程中,栈外(没进栈)有括号冗余,但此时栈空了,无法寻找与之匹配的对象
class Solution {
public:
//分析
//1.匹配结束,仍有括号剩余没有匹配(已进栈),因此栈不为空
//2.在匹配过程中,发现无与之匹配的前括号
//3.在匹配过程中,栈外(没进栈)有括号冗余,但此时栈空了,无法寻找与之匹配的对象
bool isValid(string 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('}');
//2.在匹配过程中,发现无与之匹配的前括号
//3.在匹配过程中,栈外(没进栈)有括号冗余,但此时栈空了,无法寻找与之匹配的对象
else if(st.empty() || st.top()!=s[i]) return false;
else st.pop();
}
//1.匹配结束,仍有括号剩余没有匹配(已进栈),因此栈不为空
return st.empty();
}
};
这里再详细演示一遍推理的思路,还有不懂的小伙伴可以再理一理
①首先入栈大括号{(左)
②然后入栈小括号(左)
③接着即将入栈小括号)(右),[先进行判断,此时还没有入栈],从而判断出与刚才的形成了一对,那之前入栈的左小括号便出栈
④入栈中括号[(左)
⑤入栈小括号((左)
⑥同理,这里的右小括号与上一个左小括号形成配对,故左小括号出栈
⑦这里的右中括号与上一个左中括号形成配对,故左中括号出栈
⑧此时栈中只剩下一个大左括号,与即将入栈的大有括号又形成了配对,所以大左括号出栈
⑨最后全部元素均出栈,因此栈为空,st.empty()返回的便是true;
先给出代码:
class Solution {
public:
bool isValid(string s) {
unordered_map<char,int> m{{'(',1},{'[',2},{'{',3},
{')',4},{']',5},{'}',6}};
stack<char> st;
bool istrue=true;
for(char c:s){
int flag=m[c];
if(flag>=1&&flag<=3) st.push(c);
else if(!st.empty()&&m[st.top()]==flag-3) st.pop();
else {istrue=false;break;}
}
if(!st.empty()) istrue=false;
return istrue;
}
};
接下来讲解一下:
两个月前做的这道题,前几天又看到,用C实现了一遍,故而做一个补充
typedef int STDateType;
typedef struct Stack {
STDateType* a; //栈元素
int top; //栈顶指针
int capaity; //容量
}ST;
void InitStack(ST* s);
void DestoryStack(ST* s);
void Push(ST* s,STDateType x);
void Pop(ST* s);
bool StackEmpty(ST* s);
STDateType Top(ST* s);
int StackSize(ST* s);
bool isValid(char * s){
ST st;
InitStack(&st);
while(*s)
{
//1.若为左括号,则入栈
if((*s == '(')
|| (*s == '{')
|| (*s == '['))
{
Push(&st,*s);
++s;
}
else //2.若为有括号,则进行判断匹配
{
//若匹配到右括号后无左括号与之匹配,返回false
if(StackEmpty(&st))
return false;
STDateType top = Top(&st);
Pop(&st);
if(top == '(' && *s != ')'
|| top == '{' && *s != '}'
|| top == '[' && *s != ']')
{
DestoryStack(&st);
return false;
}
else
++s;
}
}
//若在匹配完成后栈不为空,则表示还要括号没有完成匹配
if(!StackEmpty(&st))
return false;
DestoryStack(&st);
return true;
}
/*初始化栈*/
void InitStack(ST* s)
{
/**
* 初始化时,top给的是0,意味着top指向栈顶数据的下一个
* 初始化时,top给的是-1,意味着top指向栈顶数据
*/
assert(s);
s->a = NULL;
s->top = 0; //先入栈再后移栈顶指针
//s->top = -1; 先移栈顶指针再入栈
s->capaity = 0;
}
/*销毁栈*/
void DestoryStack(ST* s)
{
assert(s);
free(s->a);
s->a = NULL;
s->top = s->capaity = 0;
}
/*入栈*/
void Push(ST* s,STDateType x)
{
assert(s);
//判断栈满的情况
if (s->top == s->capaity)
{
//若栈满,则执行扩容
int newCapacity = s->capaity == 0 ? 4 : s->capaity * 2;
//STDateType* tmp = (STDateType*)malloc(sizeof(STDateType*) * newCapacity);
STDateType* tmp = (STDateType*)realloc(s->a, sizeof(STDateType) * newCapacity);
if (tmp == NULL)
{
printf("realloc fail\n");
exit(-1);
}
//更新扩容后的栈数据
s->a = tmp;
s->capaity = newCapacity;
}
s->a[s->top] = x;
s->top++;
}
/*出栈*/
void Pop(ST* s)
{
assert(s);
assert(s->top > 0);
s->top--;
}
/*判断栈是否为空*/
bool StackEmpty(ST* s)
{
return s->top == 0;
}
/*取栈顶元素*/
STDateType Top(ST* s)
{
assert(s);
assert(!StackEmpty(s));
return s->a[s->top - 1];
}
/*求栈大小*/
int StackSize(ST* s)
{
assert(s);
return s->top;
}
//若匹配到右括号后无左括号与之匹配,返回false
if(StackEmpty(&st))
return false;
以上就是对于【力扣20.有效的括号】的三种解法,分别是暴力、分支和哈希,其中还是分支判断比较好理解一下,哈希表的话效率较高一些,可以做提升,暴力的话不太推荐,看一遍就行,这种自己也能写出来。好啦,最后谢谢您对本文的观看,如果觉有有什么问题请于评论区留言或者私信我都可以,觉得写的还可以的话就留下你的小红心吧❤️