「这是我参与2022首次更文挑战的第13天,活动详情查看:2022首次更文挑战」
前言
今天这道题是一个递归调用与栈结合的应用题,求解函数的独占时间,话不多说,看题,题目稍长我这里省略了,大家如果看不懂可以去leetcode看下。
题目描述
636. 函数的独占时间
- 题给描述函数调用的字符串数组用来标识n道函数的调用时间
例如:输入:n = 2, logs = ["0:start:0","1:start:2","1:end:5","0:end:6"]
- 其中n=2表示该数组中描述了两个函数的调用时间
- logs中每一项的首位如0、1、1、0标识是哪一个函数
- start和end标识函数的开始调用和调用结束
- 每一项的末位代表函数开始或结束调用的时间点
- 我们要做的是算出每个函数的执行独占时间并且按照logs中的顺序放到数组中返回出来
演示上面例子的运算过程:-
函数0在时间0开始执行,在时间6结束执行,总时间7
-
函数1在时间2开始执行,在时间5结束执行,总时间4
-
所以得出函数0的独占时间为7-4=3,我们的
最终结果res为[3,4],3为0函数的独占时间,4为1函数的独占时间
-
解题思路
下面这幅图我举了3种不同的例子,普通函数和递归调用函数,首先说明一下,我们本题中的函数是可以递归调用的,也就是相同标识0的函数,可以有多个start标识项,当然每个start都有与之配对的end项,代表相同标识的函数在递归调用,我们把最外围的函数作为主函数,内部的函数分为普通子函数和递归子函数
从这三幅图,我们可以总结出:
每个函数调用的总时长其实都是它的执行时间点相减再加1,因为我们每个函数都可能有子函数,所以我们
想要求函数的独占时间,就需要先计算它的子函数的独占时间,最后用函数执行总时间减去子函数的执行时间即可,所以后面会用到我们的递归思想,深度优先执行调用子函数的独占时间
开始解题
var exclusiveTime = function(n, logs) {
let res = new Array(n).fill(0); // 初始化结果数组,有n道函数就是有n个元素的结果数组,时间是数字表示,填充0占位
let i = 0;
function nextTask() {
let childT = 0;
const start = logs[i].split(':'); // 当前遍历函数
while (i < logs.length - 1 && logs[i + 1].indexOf('s') !== -1) { // 当前循环为深度遍历子函数
i++;
childT = childT + nextTask(); // 每个子函数的执行时间叠加
}
const end = logs[++i].split(':');
let thisT = Number(end[2] - start[2]) + 1 - childT; // 当前函数总时间去掉所有子函数的执行时间
res[Number(start[0])] = res[Number(start[0])] + thisT; // 填充当前函数的执行时间,每次递归会更新res[Number(start[0])],最开始是0,从最内部的子函数开始加
return thisT + childT; // 返回当前函数的总时间
}
while (i < logs.length) {
nextTask(res);
i++;
}
return res;
};