Leetcode:636,函数独占时间,考查知识点:栈

一、题目描述:

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

每个函数都有一个唯一的 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 个时间单位。
说明:

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/exclusive-time-of-functions
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

二、解题思路:

1)首先要解析所有日志字符串,提取函数ID、起始时间/结束时间、时间,并保存

2)遍历所有的日志信息

     --如果是起始时间,则入栈

     --如果为结束时间:

               将栈顶元素出栈,并用当前日志的时间-出栈元素的时间 + 1,得到当前函数的运行时间

               如果栈不为空,则栈顶元素对应函数的时间运行时间 - 刚出栈函数所运行的时间

3)返回所有函数所运行的时间

 

三、具体代码:

 

#include <string.h>

#define VOS_TRUE 1

#define VOS_FALSE 0

#define VOS_ERROR (-1)

 

typedef enum tagTimeType {

    TIME_FLG_S = 0,

    TIME_FLG_E,

}TimeType;

 

/*  用于提取每天日志的信息:函数ID,时间类型,时间 */

typedef struct tagFunc {

    int funcId;

    TimeType type;

    int time;

}Func;

 

int GetFuncId(char *str)

{

    int funcId;

    if (str == NULL) {

        return -1;

    }

    funcId = atoi(str);

    return funcId;

}

 

int GetFuncTime(char *str, TimeType *type)

{

    int time;

    char *pos = NULL;

    if (str == NULL) {

        return -1;

    }

 

    pos = strstr(str, "start:");

    if (pos != NULL) {

        time = atoi(pos + 6);

        *type = TIME_FLG_S;

        return time;

    }

    pos = strstr(str, "end:");

    if (pos != NULL) {

        time = atoi(pos + 4);

        *type = TIME_FLG_E;

        return time;

    }

    return -1;

}

 

void GetAllFuncTimeInfo(char ** logs, int logsSize, Func *funcTimeInfo)

{

    int i;

    int funcId;

    int time;

    TimeType type;

    for (i = 0; i < logsSize; i++) {

        funcId = GetFuncId(logs[i]);

        time = GetFuncTime(logs[i], &type);

        if (time == -1) {

            printf("Get Time ERROR !\n");

            return;

        }

        funcTimeInfo[i].funcId = funcId;

        funcTimeInfo[i].type = type;

        funcTimeInfo[i].time = time;

    }

 

    return;

}

void PushStack(Func *funArry, Func funcInfo, int top)

{

    if (funArry == NULL) {

        return;

    }

    memcpy(&funArry[top], &funcInfo, sizeof(Func));

    return;

}

 

void PopStack(Func *funArry, Func *funcInfo, int top)

{

    if (top < 0 || funArry == NULL) {

        printf("pop fail !\r\n");

        return;

    }

    memcpy(funcInfo, &funArry[top], sizeof(Func));

    return;

}

void ClcFuncUseTimeLen(Func *funcInfo, int num, /*PSTATCK statck,*/ int *arry)

{

    int i;

    Func funcTempInfo;

    int useTime = 0;

    int top = -1;

    Func *funcArry = (Func*)malloc(num * sizeof(Func));

 

    if (funcInfo == NULL || arry == NULL || funcArry == NULL) {

        return;

    }

 

    memset(funcArry, 0, num * sizeof(Func));

    for (i = 0; i < num; i++) {

        /* 如果函数时间类型为Start,则入栈*/

        if (funcInfo[i].type == TIME_FLG_S) {

            top++;

            pushStack(funcArry, funcInfo[i], top);         

        } else {        

            popStack(funcArry, &funcTempInfo, top);

            top--;

            useTime = funcInfo[i].time - funcTempInfo.time + 1;

            arry[funcTempInfo.funcId] += useTime;

            /* 如果栈顶元素不为空,则说明栈顶元素调用了出栈的元素 */

            /* 那么栈顶函数的运行时间应该减去出栈元素的运行时间 */

            if (top != -1) {

                popStatck(funcArry, &funcTempInfo, top);

                arry[funcTempInfo.funcId] -= useTime;

            }

        }

    }

    free(funcArry);

    funcArry = NULL;

    return;

}

 

/**

 * Note: The returned array must be malloced, assume caller calls free().

 */

int* exclusiveTime(int n, char ** logs, int logsSize, int* returnSize) {

 

    Func *funcInfo = NULL;

    int *arry = NULL;

 

    /* 申请一个一维数组用于保存每个函数消耗的时间 */

    arry = (int*)malloc(sizeof(int) * n);

    if (arry == NULL) {

        *returnSize = 0;

        return NULL;

    }

    /* 初始化*/

    memset(arry, 0, sizeof(int) * n);

    /* 申请logsize */

    funcInfo = (Func*)malloc(sizeof(Func) * logsSize);

    if (funcInfo == NULL) {

        *returnSize = 0;

        return NULL;

    }

    memset(funcInfo, 0, sizeof(Func) * logsSize);

    /* 获取所有 func的时间,起始和结束 */

    GetAllFuncTimeInfo(logs, logsSize, funcInfo);

    ClcFuncUseTimeLen(funcInfo, logsSize, arry);

    *returnSize = n;

    return arry;

}

四、个人写代码中犯的错误

1)刚开始认为,函数调用时对称的,通过函数ID区分按照对称实现,只通过5个用例

2)认为logsize 为n的两倍

3)通过真正实现一个栈来实现该功能,耗费时间较多,应该使用数组,模拟栈

4) 关键算法没有想明白

    /* 如果栈顶元素不为空,则说明栈顶元素调用了出栈的元素  那么栈顶函数的运行时间应该减去出栈元素的运行时间  */

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值