前端算法小白攻略29-leetcode(函数的独占时间)

122 阅读3分钟

「这是我参与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项,代表相同标识的函数在递归调用,我们把最外围的函数作为主函数,内部的函数分为普通子函数和递归子函数

image.png 从这三幅图,我们可以总结出: 每个函数调用的总时长其实都是它的执行时间点相减再加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;
};