Exclusive Time of Functions 函数的独占时间

给出一个非抢占单线程CPU的 个函数运行日志,找到函数的独占时间。

每个函数都有一个唯一的 Id,从 0 到 n-1,函数可能会递归调用或者被其他函数调用。

日志是具有以下格式的字符串:function_id:start_or_end:timestamp。例如:"0:start:0" 表示函数 0 从 0 时刻开始运行。"0:end:0" 表示函数 0 在 0 时刻结束。

函数的独占时间定义是在该方法中花费的时间,调用其他函数花费的时间不算该函数的独占时间。你需要根据函数的 Id 有序地返回每个函数的独占时间。

示例 1:

输入:
n = 2
logs = 
["0:start:0",
 "1:start:2",
 "1:end:5",
 "0:end:6"]
输出:[3, 4]
说明:
函数 0 在时刻 0 开始,在执行了  2个时间单位结束于时刻 1。
现在函数 0 调用函数 1,函数 1 在时刻 2 开始,执行 4 个时间单位后结束于时刻 5。
函数 0 再次在时刻 6 开始执行,并在时刻 6 结束运行,从而执行了 1 个时间单位。
所以函数 0 总共的执行了 2 +1 =3 个时间单位,函数 1 总共执行了 4 个时间单位。

说明:

  1. 输入的日志会根据时间戳排序,而不是根据日志Id排序。
  2. 你的输出会根据函数Id排序,也就意味着你的输出数组中序号为 0 的元素相当于函数 0 的执行时间。
  3. 两个函数不会在同时开始或结束。
  4. 函数允许被递归调用,直到运行结束。
  5. 1 <= n <= 100

思路:这道题用栈来做,栈里保存的是函数的id,规则如下:我们定义一个之前的时间戳preTime并初始化为0,每次我们遍历到一个新的字符串,就把对应度过的时间(当前时间time-之前的时间preTime)加到结果集res中(res初始化为全0(vector<int> res(n,0)),这里相当于是一段一段的加),更新preTime为time。然后判断类型,如果是start,就压入栈顶,如果是end就再把对应的id的时间加1,preTime也加1。这里对preTime的操作确实让人看着窒息,难以理解。我们换种思路来思考,既然要分解计算出函数的独立运行时间,那么我们就必须在函数之间插入阻断标志,比如题目给的示例:

["0:start:0",

"1:start:2",

"1:end:5",

"0:end:6"]

我们应该更新为如下形式:

["0:start:0",

"0:end:0",

"1:start:2",

"1:end:5",

"0:start:6",

"0:end:6"]

即任意两个函数之间的时间绝对不会有重叠,哪怕函数0是从6开始到6结束也绝对不会和函数1重叠(红色所示),那么我们计算每个函数的时间就很容易了,对于每个闭合区间(函数start-函数end),经过的时间等于(end-start+1)。所以对应到preTime为什么当类型为end时,preTime要加1且res[s.top()]+1,因为当前的字符串对应的操作是end,还属于当前函数的时间范围,所以对应的id的函数间隔要+1且时间preTime要往下移一位。

参考代码:

class Solution {
public:
    vector<int> exclusiveTime(int n, vector<string>& logs) {
	vector<int> res(n, 0);
	stack<int> s;
	int preTime = 0;
	for (string log:logs) {
		int found1 = log.find_first_of(":");
		int found2 = log.find_last_of(":");
		int idx = stoi(log.substr(0,found1));
		string type = log.substr(found1 + 1, found2 - found1 - 1);
		int time = stoi(log.substr(found2+1));
		if (!s.empty()) {
			res[s.top()] += time - preTime;
		}
		preTime = time;
		if (type == "start") s.push(idx);
		else {
			int tmp = s.top(); s.pop();
			++res[tmp];
			preTime++;
		}
	}
	return res;        
    }
};

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值