当前位置:首页>python>华为OD机试 - 空间占用计算(Python)

华为OD机试 - 空间占用计算(Python)

  • 2026-10-11 07:12:19
华为OD机试 - 空间占用计算(Python)

### 题目描述:

员工A的磁盘空间经常被耗尽,他需要找到占用空间最大的目录或文件,然后决定如何清理文件释放空间。给定某一目录,请编写程序帮助他统计该目录内一级子目录和文件的占用空间,并返回目标目录一级子项(文件或子目录)中占用空间最大的项。

### 规则说明

1. 目录占用空间为其内部所有文件Size的总和,且目录本身Size为0。

2. 目录深度不高于7层,目录或文件名总长度不超过128字节。

3. 当存在多个子项占用空间均为最大时,多个子项采用字符升序排列。

4. 目标目录不在文件系统中时(输入路径前缀匹配不到任何路径),返回空列表。

### 输入描述

输入:  

参数1: 要进行统计的目标目录。  

参数2: 文件系统内的文件列表。  

参数3: 文件Size列表,该列表中的数据和文件列表存在一一对应关系。

## 输出描述

输出: 目标目录一级子项(文件或子目录)中占用空间最大的项组成的列表。

### 示例1

输入:  

/dir1/dir2-1  

/dir0/dir1-1/file1-1 /dir1/dir1-1/file1-1 /dir1/dir2-1/file3-1 /dir1/dir2-1/file3-2 /dir1/dir2-1/file3-3  

8192 8192 2048 8192 1024  

输出:  

file3-2

解题思路

本题需要统计指定目录下一级子项(直接子文件或子目录)的占用空间,并返回占用空间最大的一个或多个子项(名称升序)。
目录的占用空间等于其内部所有文件大小之和(递归)。
输入给出目标目录路径、所有文件路径列表(空格分隔)、对应文件大小列表(空格分隔)。

思路一:基于路径前缀匹配 + 字典累加

  1. 将文件路径和大小存入字典(路径 → 大小)。

  2. 遍历所有文件路径,筛选出以目标目录路径为前缀的文件(注意避免前缀误匹配,如 /dir1 匹配 /dir11,需要确保目标目录后跟 / 或完全相同)。

  3. 对于每个符合条件的文件,提取相对于目标目录的剩余路径,取第一级子项名称(即剩余路径中第一个 / 之前的部分,若无 / 则为文件名本身)。

  4. 累加该文件大小到对应的一级子项。

  5. 若没有任何文件匹配,返回空列表。

  6. 找出最大总大小,收集所有达到该大小的子项,按名称升序排序,输出。

思路二:构建树形结构(字典嵌套)

  1. 将每个文件路径按 / 分割成目录/文件名列表,构建一棵多叉树,每个节点包含子节点字典和累计大小。

  2. 插入文件时,沿着路径向下创建节点,并在叶子节点(文件)上记录大小,同时向上更新父节点累计大小。

  3. 最终,目标目录对应的节点就是我们要查询的根。其直接子节点(keys)就是一级子项,每个子节点的累计大小即为该子项的占用空间。

  4. 找出累计大小最大的子项(可能有多个),按名称排序输出。

代码实现

思路一:路径前缀匹配 + 字典累加

import sysdef solve_prefix():    lines = sys.stdin.read().strip().splitlines()    if not lines:        return    target = lines[0].strip()    # 第二行:文件列表,可能为空    if len(lines) > 1:        file_paths = lines[1].strip().split()    else:        file_paths = []    # 第三行:大小列表    if len(lines) > 2:        sizes = list(map(int, lines[2].strip().split()))    else:        sizes = []    # 构建路径->大小映射    size_map = {}    for p, s in zip(file_paths, sizes):        size_map[p] = s    # 确保目标目录路径末尾不带斜杠    target = target.rstrip('/')    # 存储一级子项的总大小    sub_size = {}    for path, fsize in size_map.items():        # 检查是否在目标目录下(包括目录本身?但目录本身不是文件,所以必须深度大于)        # 如果目标目录是根目录?处理前缀匹配:要么路径等于目标目录(作为文件?但目标目录是目录,不会直接是文件),        # 要么路径以 target + '/' 开头        if path == target:            # 目标目录本身作为文件?实际上目标目录是目录,不可能有同名文件,忽略            continue        if path.startswith(target + '/'):            # 提取相对路径            rel = path[len(target)+1:]  # 去掉target和后面的/            # 取第一级子项名(第一个/之前的部分)            if '/' in rel:                sub_name = rel.split('/', 1)[0]            else:                sub_name = rel            sub_size[sub_name] = sub_size.get(sub_name, 0) + fsize    if not sub_size:        print("")        return    max_size = max(sub_size.values())    result = [name for name, size in sub_size.items() if size == max_size]    result.sort()    print(' '.join(result))if __name__ == "__main__":    solve_prefix()

思路二:构建树形结构(字典嵌套)

import sysclass TreeNode:    def __init__(self, name):        self.name = name        self.children = {}  # name -> TreeNode        self.total_size = 0  # 子树总大小(包括所有后代文件)def solve_tree():    lines = sys.stdin.read().strip().splitlines()    if not lines:        return    target = lines[0].strip()    if len(lines) > 1:        file_paths = lines[1].strip().split()    else:        file_paths = []    if len(lines) > 2:        sizes = list(map(int, lines[2].strip().split()))    else:        sizes = []    # 构建根节点(虚拟根)    root = TreeNode("")    # 插入每个文件    for path, fsize in zip(file_paths, sizes):        parts = path.split('/')        # 跳过空的部分(如第一个/导致空字符串)        parts = [p for p in parts if p]        cur = root        for i, part in enumerate(parts):            if part not in cur.children:                cur.children[part] = TreeNode(part)            cur = cur.children[part]        # 文件节点累加大小(叶子节点)        cur.total_size += fsize        # 向上更新祖先节点总大小        # 这里我们在插入后统一计算,也可以在插入时递归更新,但为避免重复,可以直接在最后递归计算        # 简便方法:插入时向上更新        # 但为了简单,我们之后对整棵树后序遍历计算    # 后序遍历计算每个节点的总大小(包括所有后代文件)    def postorder(node):        total = node.total_size  # 如果是文件节点,已有自己的大小;目录节点初始为0        for child in node.children.values():            total += postorder(child)        node.total_size = total        return total    postorder(root)    # 找到目标目录对应的节点    target_parts = [p for p in target.split('/') if p]    cur = root    for part in target_parts:        if part in cur.children:            cur = cur.children[part]        else:            # 目标目录不存在            print("")            return    # cur 为目标目录节点,其直接子节点即一级子项    if not cur.children:        print("")        return    max_size = max(child.total_size for child in cur.children.values())    result = [name for name, child in cur.children.items() if child.total_size == max_size]    result.sort()    print(' '.join(result))if __name__ == "__main__":    solve_tree()

最新文章

随机文章