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\)

image
算法

按照上面的思路,我们只需要设计一个数据结构,使得每个元素 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:
image

输入: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;
    }
};
posted @ 2023-11-25 11:41  lipu123  阅读(15)  评论(0)    收藏  举报