栈
1. 基础
栈可以用stack,或者vector来模拟操作,其实vector更方便,很多时候需要从头输出栈内元素。
没有什么写模板的必要,下面列出一些栈的基本操作
stack<int> st; vector<int> vec;
st.push(1); vec.push_back(1);
st.pop(); vec.pop_back();
int a = st.top();
int b = vec.back();
2. 进阶
什么时候入栈,什么时候出栈,是个大学问。
2434. 使用机器人打印字典序最小的字符串
本题栈操作的为t字符串,s内的字符依次入栈,而要求t中的字符出栈后拿到字典序最小的字符串。
对于当前栈顶元素top,若其字典序小于等于未入栈元素中字典序最小的,显然应当立即出栈,否则未入栈元素中字典序最小的应比当前的栈顶元素更早出栈。
string robotWithString(string s) {
string ans;
stack<int> st;
vector<int> cnt(26);
for(auto &temp : s) cnt[temp-'a']++; // 记录剩余元素出现的次数
for(auto &temp : s){
st.push(temp-'a');
cnt[temp-'a']--;
int mins = 25; // 剩余元素中字典序最小的元素
for(int i = 0; i < 25; i++)
if(cnt[i]) {mins = i; break;}
while(!st.empty() && st.top() <= mins) {
ans += st.top()+'a';
st.pop();
}
}
return ans;
}
3. 邻项消除
735.小行星碰撞
这题逻辑很简单,小行星移动速度相同,相撞只与方向相关,两颗小行星面对面相撞时,较小行星会爆炸,一样大就都爆炸。比较细节的操作是用一个参数记录当前待入栈的小行星存活状态。
vector<int> asteroidCollision(vector<int>& asteroids) {
vector<int> st;
for(auto & temp : asteroids){
bool alive = true; //记录temp是否存在
// 只有栈顶行星向右(>0) 且 temp向左(<0) 时会发生碰撞
while(alive && temp < 0 && st.size() && st.back() > 0){
alive = st.back() < -temp;
if(st.back() <= -temp) st.pop_back();
}
if(alive) st.push_back(temp);
}
return st;
}
4. 合法括号字符串(RBS)
856.括号的分数
用栈记录每层括号内部的分数。遇到'(',进入新的一层,新一层的初始分数为0;遇到')',结算当前的分数,将其×2累加到上一层。
int scoreOfParentheses(string s) {
stack<int> sums;
sums.push(0);
for(auto &temp : s){
if(temp == '(') {sums.push(0); continue;}
int v = sums.top(); sums.pop();
if(!v) sums.top() += 1;
else sums.top() += 2*v;
}
return sums.top();
}
1111.有效括号的嵌套深度
需要想到如何分配括号是合理且正确的。本题可以将深度为奇数的一对括号分配给A,深度为偶数的一对括号分配给B,保证了括号是配对的,但我不理解为什么这是深度最小的分配方式。以后回来二刷再思考一下吧。
vector<int> maxDepthAfterSplit(string seq) {
int cntl = 0;
vector<int> ans(seq.size());
for(int i = 0; i < seq.size(); i++){
if(seq[i] == '('){
cntl++; ans[i] = cntl%2;
}
else {
ans[i] = cntl%2; cntl--;
}
}
return ans;
}
5. 表达式解析
394.字符串解码
理清基本逻辑就不难。遇到数字num,把num放入数字栈nums;遇到'[',把现有的字符串res入字符串栈st;遇到']',把res复制nums.top()份,添加到st.top()后面,作为新的res,并把nums.top()和st.top()弹出;遇到字符,将其添加到res后面。最后的res即为答案。
string decodeString(string s) {
vector<int> nums;
vector<string> st;
string res;
int i = 0, n = s.size();
while(i < n){
if(s[i] >= '0' && s[i] <= '9'){
int num = 0;
while(i < n && s[i] >= '0' && s[i] <= '9'){
num = num*10 -'0' + s[i];
i++;
}
nums.push_back(num);
continue;
}
if(s[i] == '['){
st.push_back(res);
res = "";
i++; continue;
}
if(s[i] == ']'){
string nres = res;
for(int i = 1; i < nums.back(); i++) nres += res;
res = st.back() + nres;
nums.pop_back(); st.pop_back();
i++; continue;
}
res += s[i++];
}
return res;
}
6. 对顶栈
对顶栈说白了就是两个栈,左栈的顶连着右栈的顶,左栈自底向上为实际顺序,右栈自顶向下为实际顺序。
咸鱼翻身失败

浙公网安备 33010602011771号