【LeetCode】636.函数的独占时间

题目

有一个 单线程 CPU 正在运行一个含有 n 道函数的程序。每道函数都有一个位于 0 和 n-1 之间的唯一标识符。
函数调用 存储在一个 调用栈 上 :当一个函数调用开始时,它的标识符将会推入栈中。而当一个函数调用结束时,它的标识符将会从栈中弹出。标识符位于栈顶的函数是 当前正在执行的函数 。每当一个函数开始或者结束时,将会记录一条日志,包括函数标识符、是开始还是结束、以及相应的时间戳。
给你一个由日志组成的列表 logs ,其中 logs[i] 表示第 i 条日志消息,该消息是一个按 “{function_id}:{“start” | “end”}:{timestamp}” 进行格式化的字符串。例如,“0:start:3” 意味着标识符为 0 的函数调用在时间戳 3 的 起始开始执行 ;而 “1🔚2” 意味着标识符为 1 的函数调用在时间戳 2 的 末尾结束执行。注意,函数可以 调用多次,可能存在递归调用 。
函数的 独占时间 定义是在这个函数在程序所有函数调用中执行时间的总和,调用其他函数花费的时间不算该函数的独占时间。例如,如果一个函数被调用两次,一次调用执行 2 单位时间,另一次调用执行 1 单位时间,那么该函数的 独占时间 为 2 + 1 = 3 。
以数组形式返回每个函数的 独占时间 ,其中第 i 个下标对应的值表示标识符 i 的函数的独占时间。

示例 1:

输入:n = 2, logs = [“0:start:0”,“1:start:2”,“1🔚5”,“0🔚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🔚5”,“0:start:6”,“0🔚6”,“0🔚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🔚5”,“1:start:6”,“1🔚6”,“0🔚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🔚5”,“1:start:7”,“1🔚7”,“0🔚8”]
输出:[8,1]

示例 5:

输入:n = 1, logs = [“0:start:0”,“0🔚0”]
输出:[1]

提示:

  • 1 <= n <= 100
  • 1 <= logs.length <= 500
  • 0 <= function_id < n
  • 0 <= timestamp <= 109
  • 两个开始事件不会在同一时间戳发生
  • 两个结束事件不会在同一时间戳发生
  • 每道函数都有一个对应 “start” 日志的 “end” 日志

题解

每个函数必然是先开始再结束的,所以可以使用栈
入栈:

  • 遇到start进行入栈,栈元素为(id,time):函数id和函数的开始时间
  • 若不是空栈,则先计算上一个函数已经执行的时间并存入数组中:这个函数的开始时间 - 上一个函数的开始时间

出栈

  • 遇到end出栈
  • 出栈的函数和正在执行的一定是一个函数
  • 计算该函数执行时间:结束时间 - 开始时间 +1
  • 若栈不为空,则更新栈顶元素的time,即为该函数再次开始时的开始时间
class Solution {
public:
    vector<int> exclusiveTime(int n, vector<string>& logs) {
        vector<int> result(n,0);
        stack<pair<int,int>> mystack;
        for(auto& log:logs)
        {
            int id;
            char type[10];
            int time;
            sscanf(log.c_str(), "%d:%[^:]:%d", &id, type, &time);
            if(type[0] == 's')
            {
                if(!mystack.empty())
                {
                    //cout<<"start: "<<mystack.top().second<<"-"<<time<<" = "<< time - mystack.top().second<<endl;
                    result[mystack.top().first] += time - mystack.top().second;
                }
                //cout<<id<<"=="<<time<<endl;
                mystack.emplace(id,time);
            }
            else 
            {
                pair<int,int> tmp = mystack.top();
                mystack.pop();
                //cout<<"end: "<<tmp.second<<"-"<<time<<"+1 = " << time - tmp.second +1<<endl;
                result[tmp.first] += time - tmp.second + 1;
                if(!mystack.empty())
                    mystack.top().second = time+1;
            }
        }
        return result;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值