Datadog 新鲜面经: 实现 rm -rf,并避免 OOM 问题

Viewed 88

面试背景

面试中被要求实现一个类似 Linux 中 rm -rf 功能的函数,题目链接:Datadog onsite: rm -rf

系统提供以下函数:

  • Delete(path) -> bool:删除一个文件或空目录。
  • IsDirectory(path) -> bool:判断路径是否为目录。
  • GetAllFiles(path) -> List[string]:获取目录下所有文件和子目录的绝对路径。

要求实现

def DeleteAllFilesAndDir(path):
    # 实现类似于 rm -rf 的功能

初始实现:递归 DFS 版本

面试时我首先写出了一个递归实现的 DFS(深度优先搜索)版本。

面试官追问:递归实现可能导致 OOM 问题?

面试官进一步询问了递归实现的潜在问题,即是否会导致 OOM(Out Of Memory)。经过深入讨论,我指出递归实现可能引发 OOM 的主要原因包括:

  • 每一层递归调用都会占用调用栈内存,尤其是目录结构很深时容易栈溢出。
  • 当目录结构“宽”且文件数量巨大时,每次递归调用可能会持有大量的文件路径数据,导致内存爆炸。

具体讨论与场景分析

面试官补充说明了他们的实际应用场景特点:

  • 目录结构深度有限,最多 10 层。
  • 每个目录的宽度(即目录内文件或子目录数量)非常大,可能达到百万级别。

基于此信息,我进一步分析指出:

  • 深度较浅时,递归带来的栈溢出风险相对较低。
  • 但宽度巨大时,递归获取所有文件路径的中间数据集合会迅速膨胀,占用过多内存。

改进方案:迭代的 BFS 实现

为了规避上述问题,我提出了使用基于迭代的 BFS(广度优先搜索)方式来实现:

  • 使用队列数据结构逐层遍历。
  • 每次只处理当前层次的文件和目录,处理完即释放。
  • 显著降低内存占用,不再受调用栈的深度和中间数据规模的限制。

迭代 BFS 实现的优势

  • 控制内存使用,每次处理的路径数量有限。
  • 避免调用栈溢出问题。
  • 特别适用于目录结构“浅而宽”的场景。

面试结果

面试官对 BFS 迭代实现方案表示认可,并且认可了我对 OOM 问题的深入分析和合理优化方案。

顺利通过,进入下一轮面试 ✅

1 Answers

感谢贡献宝贵的面试经验!