注意事项
本文包括社招题库中的较简单题目,如华为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
| 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
| 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 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
| 输入: 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
```java package a_medium;
import java.util.*;
// https://blog.csdn.net/qq_45776114/article/details/159973125 // 准备生日礼物 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]; // 生日格式:xxxx/xx/xx,取月份 // Integer.parseInt("05") 和 Integer.parseInt("5") 都会返回整数 5。 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(); // nextInt() 不消费换行符,nextLine() 会消费换行符。两者混用时,需要手动加一个 nextLine() 来过渡。 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
输出: 0
说明: 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
| 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); } }
|
注意
该题逻辑并不复杂,但是涉及到的异常情况校验很多