返回

剖析LeetCode 636:揭秘函数的独占时间

前端

程序员经常在 LeetCode 上磨炼他们的算法和数据结构技能。 LeetCode 636 是一个尤其引人入胜的问题,它考察了程序员对线程执行和函数独占时间的理解。

问题

有一个单线程 CPU 正在运行一个含有 n 道函数的程序。每道函数都有一个位于 [start, end) 范围内的独占时间,即在这段时间内,CPU 仅执行该函数。此外,每个函数可能调用其他函数,形成一个嵌套的调用关系。

给定 n 道函数的独占时间和调用关系,要求返回每个函数的独占时间。

剖析问题

解决此问题的第一步是了解线程执行、调用栈和堆栈等关键概念:

  • 线程执行: CPU 执行程序时,会创建一个线程,该线程顺序执行程序中的指令。
  • 调用栈: 当函数调用另一个函数时,被调用函数的信息会被压入调用栈。当被调用函数返回时,它的信息会被弹出调用栈。
  • 堆栈: 堆栈是存储函数局部变量和参数的内存区域。

算法和数据结构

解决 LeetCode 636 的核心在于使用堆栈来模拟函数调用关系。具体步骤如下:

  1. 初始化: 创建一个堆栈和一个哈希表来存储函数的独占时间。
  2. 遍历日志: 按时间顺序遍历日志中的事件:
    • 如果是一次函数调用事件,则将函数信息压入堆栈,并将函数的独占时间初始化为 0。
    • 如果是一次函数返回事件,则从堆栈中弹出函数信息,并更新其独占时间。
  3. 计算独占时间: 对于堆栈中的每个函数,其独占时间等于其子函数的独占时间之和加上其自身独占时间。
  4. 返回结果: 返回哈希表中所有函数的独占时间。

代码示例

def exclusiveTime(n, logs):
    stack = []
    time = {}
    for log in logs:
        function, event, timestamp = log.split(':')
        if event == 'start':
            stack.append((int(function), int(timestamp)))
        else:
            start_function, start_time = stack.pop()
            total_time = int(timestamp) - start_time + 1
            time[start_function] = time.get(start_function, 0) + total_time
            if stack:
                time[stack[-1][0]] -= total_time
    return [time[i] for i in range(n)]

结论

通过理解线程执行、调用栈和堆栈等基本概念,程序员可以有效地解决 LeetCode 636 等复杂算法问题。该问题不仅考验了对算法和数据结构的掌握,还培养了对编程执行过程的深刻理解。