栈的进阶篇
参考资料来源灵神在力扣所发的题单,仅供分享学习笔记和记录,无商业用途。
核心思路:查看栈的基础篇-CSDN博客
应用场景:处理具有完全包含关系(括号关系)的问题,递归实现和栈实现本质上没有区别
力扣刷题
3170. 删除星号以后字典序最小的字符串
题意:
给定一个带:'*'的字符串,遇到*时需要删除它并且在它之前找到字典序最小的字符进行删除,存在多个任意删除一个,返回重构的字符串
思路:
用动态数组记录26个字符出现的位置,遇到*直接按顺序遍历26个数组,遇到存在的数组删除一个元素即可。
遍历完字符串后将26个字母动态数组存放的元素进行升序排序,变成重构字符串后的元素位置
class Solution {
public:string clearStars(string s) {//题意:给定一个带:'*'的字符串,遇到*时需要删除它并且在它之前找到字典序最小的字符进行删除,存在多个任意删除一个,返回重构的字符串//思路:用动态数组记录26个字符出现的位置,遇到*直接按顺序遍历26个数组,遇到存在的数组删除一个元素即可。//遍历完字符串后将26个字母动态数组存放的元素进行升序排序,变成重构字符串后的元素位置vector<int> ans[26];for(int i=0;i<s.size();i++){if(s[i]!='*'){ans[s[i]-'a'].push_back(i);continue;}for(auto&x:ans){if(x.size()){x.pop_back();break;}}}vector<int> buff;for(auto&x:ans) buff.insert(buff.end(),x.begin(),x.end());sort(buff.begin(),buff.end());string ret="";for(auto x:buff) ret+=s[x];return ret;}
};
155. 最小栈
题意:获取当前栈中最小元素
思路:当元素小于等于栈顶元素或者最小栈为空时才能放入。保证了栈顶为当前栈中最小元素
class MinStack {
public:vector<int> ans,ans_min;MinStack() {}//当元素小于等于栈顶元素或者最小栈为空时才能放入。保证了栈顶为当前栈中最小元素void push(int val) {ans.push_back(val);if(ans_min.empty() || ans_min.back()>=val) ans_min.push_back(val);return ;}void pop() {if(ans.empty()) return ;if(ans_min.back()==ans.back()) ans_min.pop_back();ans.pop_back(); }int top() {return ans.back();}int getMin() {return ans_min.back();}
};/*** Your MinStack object will be instantiated and called as such:* MinStack* obj = new MinStack();* obj->push(val);* obj->pop();* int param_3 = obj->top();* int param_4 = obj->getMin();*/
636. 函数的独占时间
题意:给定一组[函数编号:状态:时间]的数据,一定符合时间先后调用关系,求各个编号函数执行完需要花费多少时间
思路:
先划分好数据,用栈存储上一个开始函数并用一个变量记录上一个时间。如果栈中有函数启动并且又递归调用一个函数则先计算好前一个函数的部分时间在入栈递归函数,在统计好递归函数时间出栈递归函数后,最后统计好前函数时间。
递归的本质就是栈思想,着重理解递归与栈的关系
class Solution {
public:vector<int> exclusiveTime(int n, vector<string>& logs) {//题意:给定一组[函数编号:状态:时间]的数据,一定符合时间先后调用关系,求各个编号函数执行完需要花费多少时间//思路:先划分好数据,用栈存储上一个开始函数并用一个变量记录上一个时间。如果栈中有函数启动并且又递归调用一个函数则先计算好前一个函数的部分时间在入栈递归函数,在统计好递归函数时间出栈递归函数后,最后统计好前函数时间。//递归的本质就是栈思想,着重理解递归与栈的关系vector<int> ans(n);stack<int> vID;for(int i=0,pre=0;i<logs.size();i++){int pos1=logs[i].find_first_of(":");int pos2=logs[i].find_last_of(":");string id_str=logs[i].substr(0,pos1);string status=logs[i].substr(pos1+1,pos2-pos1-1);string time_str=logs[i].substr(pos2+1,logs[i].size()-pos2-1);int id=atoi(id_str.c_str());int time_stamp=atoi(time_str.c_str());if(!vID.empty()) ans[vID.top()]+=time_stamp-pre+(status=="end");pre=time_stamp+(status=="end");if(status=="start"){vID.push(id);}else vID.pop();}return ans;}
};
2434. 使用机器人打印字典序最小的字符串
题意:给定一个字符串按顺序全部入栈。自行选择入栈和出栈的时机,要求在入栈和出栈的过程中找到组成最小字典序的方法
思路:
在入栈后判断栈顶是否能小于后缀最小字符,能则说明是当下最优解直到栈顶大于后缀最小字符停止。
给后缀最小字符数组最后一位标记成最大字符保证在遍历字符串的最后一次能清空栈内元素归并到结果中
class Solution {
public:string robotWithString(string s) {//题意:给定一个字符串按顺序全部入栈。自行选择入栈和出栈的时机,要求在入栈和出栈的过程中找到组成最小字典序的方法//思路:在入栈后判断栈顶是否能小于后缀最小字符,能则说明是当下最优解直到栈顶大于后缀最小字符停止。//给后缀最小字符数组最后一位标记成最大字符保证在遍历字符串的最后一次能清空栈内元素归并到结果中vector<char> ans(s.size()+1);stack<char> buff;ans[s.size()]='z'; //清空栈元素for(int i=s.size()-1;i>=0;i--) ans[i]=min(ans[i+1],s[i]); //后缀最小字符string ret="";for(int i=0;i<s.size();i++){buff.push(s[i]);while(!buff.empty() && buff.top()<=ans[i+1]){ret+=buff.top();buff.pop();}}return ret;}
};