前言:本文章才开始利用栈来解决该问题,但本人认为上一节的思路更加重要,且本文章延续上一篇文章思路,所以看这篇之前最好至少大致了解一下上一节思路。
关键知识点:栈。后面说一个本人对于栈的理解,栈的本质是线性结构+仅一端操作。我希望初学者不要和我当时一样只记得”先进后出",这个是运作特性,是由前面所说的本质导致的,只记住这个是很难理解栈以至于能手写出来栈代码的。
附加:(方便理解,可直接跳过)作者刚开始学习栈的时候十分迷惑,只能在一端进行操作,感觉十分麻烦,使用起来不如数组灵活,后面的学习逐渐意识到,它的”不便利性“正是它的优势,它所能进行的操作越有限,它考虑起来越简单。举一个类似理解:bool值相对于int值,正因为它只有两个值,我们使用起来才更加直观,遇到bool值我们会直接知道这多半是用来判断。(当然存储大小也是一小点)正如一般用栈,我们就知道它多半只会在一端进行操作。总言之,就是解决同一个问题,模型越简单越好,栈的操作有限性照成了它的简单性带来了便利。
如上篇文章结束所言,我们仅对线性结构(字符串)一端进行操作,这符合栈的特性(线性结构+仅一端操作)。上篇文章中仅在一端操作的线性结构是等级数组level[10000],故我们可以转换为栈,当需要进元素时(遇到左括号)利用栈的push();当需要弹出元素与所遇到符号对比时(遇到右括号)利用栈的pop()。
希望你看到这可以自己写出后面代码。
#include<stack>
class Solution {
public:
bool isValid(string s) {
int small, medium, large;
small = medium = large = 0;
stack<int> level;//int level[10000] = {0};
int levelFlag = 0;
for (int i = 0; i < s.length(); i++){
if(s[i] == '('){
small += 1;//handle require 1
level.push(1);//也可以改成"(",直接用符号进行对比
//levelFlag+=1;
//level[levelFlag] = 1;
}
else if(s[i] == ')'){
small -= 1; //handle require 1
if(small < 0)
return false;
int levelTop = -1;
if (!level.empty())
levelTop = level.top();
level.pop();
if(levelTop != 1)
return false;
/*
if(level[levelFlag] == 1){//handle require 2
levelFlag--;
}else
return false; //no match
*/
}
else if(s[i] == '['){
medium += 1;
level.push(2);
//levelFlag+=1;
//level[levelFlag] = 2;
}
else if(s[i] == ']'){
medium -= 1;
if(medium < 0)
return false;
int levelTop = -1;
if (!level.empty())
levelTop = level.top();
level.pop();
if(levelTop != 2 )
return false;
/*
if(level[levelFlag] == 2)
levelFlag--;
else
return false;
*/
}
else if(s[i] == '{')
{
large += 1;
level.push(3);
//levelFlag+=1;
//level[levelFlag] = 3;
}
else{
large -= 1;
int levelTop = -1;
if (!level.empty())
levelTop = level.top();
level.pop();
if(levelTop != 3)
return false;
/*
if(large < 0)
return false;
if(level[levelFlag] == 3)
levelFlag--;
else
return false;
*/
}
}
if(large > 0 || medium > 0 || small > 0 )
return false;
return true;
}
};
很明显,这个代码十分的丑陋,并且还调用了库函数,应该比网上任何代码都要差劲,但它运行效率并不会低于其他代码,是一个“正确”的答案。希望读者能够理解为什么这里需要用到栈,为什么是对符号进行建立栈,以及在写后缀表达式这类题目时能够理解为什么要对符号建栈,为什么进去时需要等级对比。
总结:如果有不了解库函数的同学,可以自行搜索一下,最好是自己手写出来,这并不困难。希望特别是初学者一定要自己写出来,即使是写了一天,也比抄别人代码,仅从表面上理解要好,写完了再去与网上更优秀的代码对比。
文章不足之处,不方便理解处待指正。
题目力扣链接:https://leetcode.cn/problems/valid-parentheses/