leetcode中的栈
最小栈
https://leetcode.cn/problems/min-stack/description/
设计一个支持\(push\),\(pop\) ,\(top\) 操作,并能在常数时间内检索到最小元素的栈。
实现 MinStack 类:
MinStack() 初始化堆栈对象。
void push(int val) 将元素val推入堆栈。
void pop() 删除堆栈顶部的元素。
int top() 获取堆栈顶部的元素。
int getMin() 获取堆栈中的最小元素。
示例 1:
输入:
["MinStack","push","push","push","getMin","pop","top","getMin"]
[[],[-2],[0],[-3],[],[],[],[]]
输出:
[null,null,null,null,-3,null,0,-2]
解释:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.getMin(); --> 返回 -2.
提示:
\(-2^31 <= val <= 2^31 - 1\)
pop、top 和 getMin 操作总是在 非空栈 上调用
push, pop, top, and getMin最多被调用\(3 * 10^4\)次
算法
按照上面的思路,我们只需要设计一个数据结构,使得每个元素 a 与其相应的最小值 m 时刻保持一一对应。因此我们可以使用一个辅助栈,与元素栈同步插入与删除,用于存储与每个元素对应的最小值。
当一个元素要入栈时,我们取当前辅助栈的栈顶存储的最小值,与当前元素比较得出最小值,将这个最小值插入辅助栈中;
当一个元素要出栈时,我们把辅助栈的栈顶元素也一并弹出;
在任意一个时刻,栈内元素的最小值就存储在辅助栈的栈顶元素中。
class MinStack {
public:
stack<int> x_stack;
stack<int> min_stack;
MinStack() {
min_stack.push(INT_MAX);// 因为后面Push的时候要取min_stack_top进行比较
}
void push(int val) {
x_stack.push(val);
min_stack.push(min(val,min_stack.top()));
}
void pop() {
x_stack.pop();
min_stack.pop();
}
int top() {
return x_stack.top();
}
int getMin() {
return min_stack.top();
}
};
/**
* 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();
*/
函数的独占时间
有一个 单线程 CPU 正在运行一个含有\(n\)道函数的程序。每道函数都有一个位于\(0\)和\(n-1\)之间的唯一标识符。
函数调用存储在一个调用栈上 :当一个函数调用开始时,它的标识符将会推入栈中。而当一个函数调用结束时,它的标识符将会从栈中弹出。标识符位于栈顶的函数是 当前正在执行的函数 。每当一个函数开始或者结束时,将会记录一条日志,包括函数标识符、是开始还是结束、以及相应的时间戳。
给你一个由日志组成的列表\(logs\),其中\(logs[i]\)表示第\(i\)条日志消息,该消息是一个按\("{function_id}:{"start" | "end"}:{timestamp}"\)进行格式化的字符串。例如,\("0:start:3"\)意味着标识符为\(0\)的函数调用在时间戳\(3\)的 起始开始执行 ;而\("1:end:2"\) 意味着标识符为\(1\)的函数调用在时间戳\(2\)的 末尾结束执行。注意,函数可以 调用多次,可能存在递归调用 。
函数的 独占时间 定义是在这个函数在程序所有函数调用中执行时间的总和,调用其他函数花费的时间不算该函数的独占时间。例如,如果一个函数被调用两次,一次调用执行 2 单位时间,另一次调用执行 1 单位时间,那么该函数的 独占时间 为 2 + 1 = 3 。
以数组形式返回每个函数的 独占时间 ,其中第 i 个下标对应的值表示标识符 i 的函数的独占时间。
示例 1:
输入:n = 2, logs = ["0:start:0","1:start:2","1: end:5","0: end:6"]
输出:[3,4]
解释:
函数 0 在时间戳 0 的起始开始执行,执行 2 个单位时间,于时间戳 1 的末尾结束执行。
函数 1 在时间戳 2 的起始开始执行,执行 4 个单位时间,于时间戳 5 的末尾结束执行。
函数 0 在时间戳 6 的开始恢复执行,执行 1 个单位时间。
所以函数 0 总共执行 2 + 1 = 3 个单位时间,函数 1 总共执行 4 个单位时间。
示例 2:
输入:n = 1, logs = ["0:start:0","0:start:2","0: end:5","0:start:6","0: end:6","0: end:7"]
输出:[8]
解释:
函数 0 在时间戳 0 的起始开始执行,执行 2 个单位时间,并递归调用它自身。
函数 0(递归调用)在时间戳 2 的起始开始执行,执行 4 个单位时间。
函数 0(初始调用)恢复执行,并立刻再次调用它自身。
函数 0(第二次递归调用)在时间戳 6 的起始开始执行,执行 1 个单位时间。
函数 0(初始调用)在时间戳 7 的起始恢复执行,执行 1 个单位时间。
所以函数 0 总共执行 2 + 4 + 1 + 1 = 8 个单位时间。
示例 3:
输入:n = 2, logs = ["0:start:0","0:start:2","0: end:5","1:start:6","1: end:6","0: end:7"]
输出:[7,1]
解释:
函数 0 在时间戳 0 的起始开始执行,执行 2 个单位时间,并递归调用它自身。
函数 0(递归调用)在时间戳 2 的起始开始执行,执行 4 个单位时间。
函数 0(初始调用)恢复执行,并立刻调用函数 1 。
函数 1在时间戳 6 的起始开始执行,执行 1 个单位时间,于时间戳 6 的末尾结束执行。
函数 0(初始调用)在时间戳 7 的起始恢复执行,执行 1 个单位时间,于时间戳 7 的末尾结束执行。
所以函数 0 总共执行 2 + 4 + 1 = 7 个单位时间,函数 1 总共执行 1 个单位时间。
示例 4:
输入:n = 2, logs = ["0:start:0","0:start:2","0: end:5","1:start:7","1: end:7","0: end:8"]
输出:[8,1]
示例 5:
输入:n = 1, logs = ["0:start:0","0: end:0"]
输出:[1]
提示:
\(1 <= n <= 100\)
\(1 <= logs.length <= 500\)
\(0 <= function_id < n\)
\(0 <= timestamp <= 10^9\)
两个开始事件不会在同一时间戳发生
两个结束事件不会在同一时间戳发生
每道函数都有一个对应 "start" 日志的 "end" 日志
其实就是用栈进行模拟
class Solution {
public:
vector<int> solve(string s){
vector<int> ans;
int i;
int z=0;
for(i=0;i<s.size();i++){
if(s[i]==':'){
break;
}
z=z*10+(s[i]-'0');
}
ans.push_back(z);
i++;
if(s[i]=='s'){
ans.push_back(0);
}
else{
ans.push_back(1);
}
for(;i<s.size();i++){
if(s[i]==':'){
break;
}
}
i++;
z=0;
for(;i<s.size();i++){
z=z*10+(s[i]-'0');
}
ans.push_back(z);
return ans;
}
vector<int> exclusiveTime(int n, vector<string>& logs) {
stack<int> a;
stack<int> op;
stack<int> s;
int m=logs.size();
vector<int> res(n);
for(int i=0;i<m;i++){
vector<int> ans=solve(logs[i]);
if(i==0||a.empty()){
a.push(ans[0]);
op.push(ans[1]);
s.push(ans[2]);
}
else{
if(ans[1]==0){
int aa=a.top();
res[aa]+=(ans[2]-s.top());
a.push(ans[0]);
op.push(ans[1]);
s.push(ans[2]);
}else{
int aa=a.top();
int ss=s.top();
res[aa]+=(ans[2]-ss+1);
a.pop(),op.pop(),s.pop();
if(!s.empty())
s.top()=ans[2]+1;
}
}
}
return res;
}
};