注意事项
本文包括社招题库中的较简单题目,如华为OD中分值为100的题目
模拟 空间占用计算
题目描述
员工A的磁盘空间经常被耗尽,他需要找到占用空间最大的目录或文件,然后决定如何清理文件释放空间。
给定某一目录,请写那些程序帮他统计目录内一级子目录和文件的占用空间,并返回目标目录一级子项(文件或子目录)中占用空间最大的项。
规则说明
目录占用空间为其内部所有文件 Size 的总和,目录本身 Size 为0
目录深度不高于 7,目录或文件名总长度不超过 128 字节
当存在多个子项占用空间均为最大时,多个子项采用字符升序排列。
目标目录不再文件系统中时(输入路径前缀匹配不到任何路径),返回空列表。
输入描述
输入要统计的目标目录
文件系统内的文件列表
文件 Size 列表,该列表中的数据和文件列表存在一一对应关系。
输出描述
目标目录一级子项(文件或子目录)中占用空间最大的项组成的列表。
用例 1:
1 2 3 4 5 6 7 输入: /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 81920 2048 8192 1024 输出: file3-2
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 package a_medium;import java.util.*;public class a01_space_occupation_calculation { static class Node { Map<String, Node> childrenDir = new HashMap <>(); Map<String, Node> childrenFile = new HashMap <>(); String name; int size = 0 ; } static int dfs (Node root) { int sum = 0 ; for (Node node : root.childrenDir.values()) { sum += dfs(node); } for (Node node : root.childrenFile.values()) { sum += node.size; } root.size = sum; return sum; } public static void main (String[] args) { Scanner sc = new Scanner (System.in); String path = sc.nextLine(); String file = sc.nextLine(); String fileSize = sc.nextLine(); String[] fileList = file.split(" " ); String[] sizeArr = fileSize.split(" " ); Node root = new Node (); for (int i = 0 ; i < fileList.length; i++) { String[] parts = fileList[i].split("/" ); Node cur = root; for (int j = 1 ; j < parts.length; j++) { String name = parts[j]; boolean isFile = (j == parts.length - 1 ); if (!isFile) { cur.childrenDir.putIfAbsent(name, new Node ()); cur.childrenDir.get(name).name = name; cur = cur.childrenDir.get(name); } else { Node fileNode = new Node (); fileNode.name = name; fileNode.size = Integer.parseInt(sizeArr[i]); cur.childrenFile.put(name, fileNode); } } } Node cur = root; String[] parts = path.split("/" ); for (int i = 1 ; i < parts.length; i++) { if (!cur.childrenDir.containsKey(parts[i])) { return ; } cur = cur.childrenDir.get(parts[i]); } dfs(cur); List<Node> list = new ArrayList <>(); list.addAll(cur.childrenDir.values()); list.addAll(cur.childrenFile.values()); if (list.isEmpty()) return ; list.sort((a, b) -> { if (a.size == b.size) return a.name.compareTo(b.name); return b.size - a.size; }); int max = list.get(0 ).size; for (Node node : list) { if (node.size != max) break ; System.out.print(node.name + " " ); } } }
注意
这道题的核心就是模拟。 它模拟了文件系统的目录结构:
用树形结构模拟目录和文件的层级关系
模拟了”构建目录 → 查找目标路径 → 计算大小 → 排序输出”的完整流程
计算数列位置N的值
题目描述
输入 M,N 两个数,则按照以下规则形成一个数列。
数列的前 M 个元素的值为 1 到 M
从 M+1 个元素开始,计算逻辑为
如果其前 M 个元素中,存在值相同的元素,则该位置上的数值等于前 M 个数中最大数值与最小数值之和。
如果其前 M 个元素中,不存在值相同的元素,则该位置上的数值等于前 M 个数中最大的数值和最小数值之差。 请计算该数列第 N 个位置上的数值
补充
3 <= M <= 10
1 <= N <= 50
输入描述
输出N和M,使用 , 分割
输出描述
输出N位置上的数值
用例1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 package a_medium;import java.util.*;public class a02_calculate_the_value_at_position_N { public static int positionValue (int m, int n) { if (n <= m) { return n; } int [] num = new int [n + 1 ]; for (int i = 1 ; i <= m; i++) { num[i] = i; } for (int i = m + 1 ; i <= n; i++) { int mx = Integer.MIN_VALUE, mn = Integer.MAX_VALUE; HashSet<Integer> set = new HashSet <>(); boolean dupFlag = false ; for (int j = i - m; j < i; j++) { if (set.contains(num[j])) { dupFlag = true ; } set.add(num[j]); mx = Math.max(mx, num[j]); mn = Math.min(mn, num[j]); } if (dupFlag) { num[i] = mx + mn; } else { num[i] = mx - mn; } } return num[n]; } public static void main (String[] args) { Scanner sc = new Scanner (System.in); String input = sc.nextLine(); String[] parts = input.split("," ); int m = Integer.parseInt(parts[0 ]); int n = Integer.parseInt(parts[1 ]); System.out.println(positionValue(m, n)); } }
准备生日礼物
题目描述 小明在一个充满人文关怀的公司上班,公司每个月都要为该月生日的同事送一份生日小礼物,该事项由小明负责,请帮助小明统计某一月份应该准备多少礼物,重复录入的员工生日以最后一次录入结果为准,请不要重复统计,避免浪费。
输入描述 参数 1,要发放礼物的月份,取值 1 到 12。 参数 2,员工列表。 参数 3,员工生日日期列表,该列表和员工列表中的数据对应存在一一对应关系,长度一致。
输出描述 该月份要准备的礼品个数。
补充说明
小明公司的员工人数不超过 100 人。
员工姓名是字母和数字的组合,姓名长度大于 0,小于 16 字节。
日期录入格式统一采用 Year/Month/Day , Year 长度为 4, Month和 Day 长度为 1 到 2,系统保证录入日期为合法日期。
不考虑同名多位员工的情况,名字一致即可认为是同一员工(在生产系统会通过工号区分,本系统简化处理)。
用例1
1 2 3 4 5 6 7 输入: 5 Alice Bob Charlie David Eve Frank Grace Helen 1985/5/10 1990/10/11 1995/10/11 2000/11/10 2005/05/01 2010/10/13 2015/10/14 2020/5/2 输出: 3
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 package a_medium;import java.util.*;public class a03_prepare_a_birthday_gift { public static int calGiftNum (int month, String[] names, String[] birthdays) { Map<String, Integer> nameMonth = new HashMap <>(); for (int i = 0 ; i < names.length; i++) { String currentName = names[i]; String currentBirthday = birthdays[i]; int m = Integer.parseInt(currentBirthday.split("/" )[1 ]); nameMonth.put(currentName, m); } int count = 0 ; for (int m : nameMonth.values()) { if (m == month) { count++; } } return count; } public static void main (String[] args) { Scanner sc = new Scanner (System.in); int month = sc.nextInt(); sc.nextLine(); String name = sc.nextLine(); String birthday = sc.nextLine(); String[] names = name.split(" " ); String[] birthdays = birthday.split(" " ); int res = calGiftNum(month, names, birthdays); System.out.println(res); } }
配置操作失败数量统计
题目描述 模拟一个系统的命令行配置,包含添加、修改、删除三项操作,详情如下:
添加操作命令:add_rule rule_id=1 rule_index=18
修改操作命令:mod_rule rule_id=1 rule_index=100
删除操作命令:del_rule rule_id=1
其中:add_rule、mod_rule、del_rule 是操作关键字,rule_id和rule_index是属性关键字且属性取值范围为数字 1 - 9999 之间,操作、属性之间都用空格进行分割。
在进行所有操作时,如果缺少关键字,或者相应的 rule_id、rule_index 的取值不符合要求,则操作失败。
在进行添加操作时,参数必须包含 rule_id 和 rule_index,如果当前不存在,则添加成功,如果添加已经存在的 rule_id,则操作失败。
在进行修改操作时,参数必须包含 rule_id 和 rule_index,如果当前 rule_id 不存在,或前后 rule_index 没有变化,则操作失败。
在进行删除操作时,参数必须包含 rule_id,如果当前 rule_id 不存在,则操作失败。
在进行批量操作时,一个命令失败后可以继续下一条命令的操作。现给有一组批量操作的字符串,包括不超过 1000 条连续的操作指令,格式为 [cmd][cmd][cmd],请将字符串解析后按照顺序进入你实现的系统,统计出配置失败的次数。
输入描述 输入命令以空格分割
输出描述 输出失败命令数量
用例1
1 2 3 4 5 6 7 8 9 10 输入: add_rule rule_id=1 rule_index=9999 mod_rule rule_id=1 rule_index=10 del_rule rule_id=1 输出: 0 说明: 所有操作都成功。
用例2
1 2 3 4 5 6 7 8 9 10 输入: add_rule rule_id=1 mod_rule rule_id=1 rule_index=10 del_rule rule_id=1 输出: 3 说明: add操作不包含rule_index,添加失败,后续修改和删除操作,无对应rule_id数据,也会失败。
用例3
1 2 3 4 5 6 7 8 输入: add_rule rule_id=1 rule_index=10000 输出: 1 说明: rule_index超过范围
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 package a_medium;import java.util.*;public class a04_configuration_operation_failure_count_statistics { static boolean judegeNumber (String s) { if (s.isEmpty()) return false ; for (char c : s.toCharArray()) { if (!Character.isDigit(c)) return false ; } int num = Integer.parseInt(s); return num >= 1 && num <= 9999 ; } static int calErrorCmdError (List<String> command) { int errorCount = 0 ; Map<String, String> ruleIndex = new HashMap <>(); for (String line : command) { String[] cmd = line.split(" " ); if (cmd.length != 2 && cmd.length != 3 ) { errorCount++; continue ; } String operatorCmd = cmd[0 ]; if (operatorCmd.equals("del_rule" )) { if (cmd.length != 2 ) { errorCount++; continue ; } String[] idPropertys = cmd[1 ].split("=" ); if (idPropertys.length != 2 || !idPropertys[0 ].equals("rule_id" )) { errorCount++; continue ; } String id = idPropertys[1 ]; if (!judegeNumber(id) || !ruleIndex.containsKey(id)) { errorCount++; continue ; } ruleIndex.remove(id); } else if (operatorCmd.equals("mod_rule" ) || operatorCmd.equals("add_rule" )) { if (cmd.length != 3 ) { errorCount++; continue ; } String[] idPropertys = cmd[1 ].split("=" ); String[] indexPropertys = cmd[2 ].split("=" ); if (idPropertys.length != 2 || indexPropertys.length != 2 || !idPropertys[0 ].equals("rule_id" ) || !indexPropertys[0 ].equals("rule_index" )) { errorCount++; continue ; } String id = idPropertys[1 ]; String index = indexPropertys[1 ]; if (!judegeNumber(id) || !judegeNumber(index)) { errorCount++; continue ; } if (operatorCmd.equals("mod_rule" )) { if (!ruleIndex.containsKey(id) || ruleIndex.get(id).equals(index)) { errorCount++; continue ; } ruleIndex.put(id, index); } else { if (ruleIndex.containsKey(id)) { errorCount++; continue ; } ruleIndex.put(id, index); } } else { errorCount++; } } return errorCount; } public static void main (String[] args) { Scanner sc = new Scanner (System.in); List<String> cmd = new ArrayList <>(); while (sc.hasNextLine()) { String line = sc.nextLine(); if (line.isEmpty()) break ; cmd.add(line); } int errorCount = calErrorCmdError(cmd); System.out.println(errorCount); } }
注意
该题逻辑并不复杂,但是涉及到的异常情况校验很多