2025 A卷 100分 题型
本专栏内全部题目均提供Java、python、JavaScript、C、C++、GO六种语言的最佳实现方式;
并且每种语言均涵盖详细的问题分析、解题思路、代码实现、代码详解、3个测试用例以及综合分析;
本文收录于专栏:《2025华为OD真题目录+全流程解析+备考攻略+经验分享》
华为OD机试真题《考勤信息》:
文章快捷目录
题目描述及说明
Java
python
JavaScript
C++
C
GO
更多内容
题目名称:考勤信息
- 知识点:字符串处理、滑动窗口、逻辑判断
- 时间限制:1秒
- 空间限制:256MB
- 限定语言:不限
题目描述
公司用一个字符串来表示员工的出勤信息,包含以下四种标记:
absent
:缺勤late
:迟到leaveearly
:早退present
:正常上班
出勤奖判定条件:
- 缺勤不超过一次;
- 没有连续的迟到/早退(即相邻记录不能同时为
late
或leaveearly
); - 任意连续7次考勤中,缺勤/迟到/早退的总次数不超过3次。
输入描述:
- 第一行为记录条数
N
(N >= 1
); - 后续
N
行为考勤记录字符串(长度< 10000
,无非法输入)。
示例:
2
present
present absent present present leaveearly present absent
输出描述:
对每组考勤记录,输出true
(可获奖)或false
(不可获奖),结果用空格分隔。
示例输出:
true false
Java
问题分析
题目要求根据员工的考勤记录判断其是否符合获得出勤奖的条件。需满足以下三个条件:
- 缺勤不超过一次;
- 没有连续的迟到或早退;
- 任意连续7次考勤中,违规次数(缺勤/迟到/早退)不超过3次。
解题思路
- 条件一:遍历所有记录,统计缺勤次数。若超过1次,直接返回
false
。 - 条件二:遍历相邻记录,若相邻两个记录均属于迟到或早退,返回
false
。 - 条件三:若记录数≥7,使用滑动窗口检查每个连续7次考勤的违规次数。若任何窗口超过3次,返回
false
。
代码实现
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int N = Integer.parseInt(scanner.nextLine()); // 读取测试用例数
StringBuilder result = new StringBuilder();
for (int i = 0; i < N; i++) {
int n = Integer.parseInt(scanner.nextLine()); // 读取当前用例的记录数
String[] records = new String[n];
for (int j = 0; j < n; j++) {
records[j] = scanner.nextLine().trim(); // 读取每条记录
}
result.append(checkAttendance(records) ? "true " : "false ");
}
System.out.println(result.toString().trim());
scanner.close();
}
private static boolean checkAttendance(String[] records) {
int n = records.length;
int absentCount = 0;
int[] violations = new int[n]; // 标记是否为违规记录(absent/late/leaveearly)
// 检查条件1和条件2,并构建violations数组
for (int i = 0; i < n; i++) {
String record = records[i];
// 条件1:统计缺勤次数
if (record.equals("absent")) {
absentCount++;
if (absentCount > 1) return false;
}
// 构建violations数组(1表示违规)
violations[i] = (record.equals("absent") || record.equals("late") || record.equals("leaveearly")) ? 1 : 0;
// 条件2:检查相邻记录是否均为迟到/早退
if (i > 0) {
String prev = records[i - 1];
boolean prevViolate = prev.equals("late") || prev.equals("leaveearly");
boolean currViolate = record.equals("late") || record.equals("leaveearly");
if (prevViolate && currViolate) return false;
}
}
// 条件3:滑动窗口检查连续7次考勤
if (n >= 7) {
int windowSum = 0;
// 初始化第一个窗口(前7个记录)
for (int j = 0; j < 7; j++) {
windowSum += violations[j];
}
if (windowSum > 3) return false;
// 滑动窗口,每次移动一步
for (int j = 7; j < n; j++) {
windowSum += violations[j] - violations[j - 7];
if (windowSum > 3) return false;
}
}
return true;
}
}
代码解析
-
输入处理:
scanner.nextLine()
读取输入,处理多个测试用例。records
数组存储每个用户的考勤记录。
-
条件一检查:
- 统计
absent
次数,超过1次直接返回false
。
- 统计
-
条件二检查:
- 遍历相邻记录,若当前和前一个记录均属于迟到/早退,返回
false
。
- 遍历相邻记录,若当前和前一个记录均属于迟到/早退,返回
-
条件三检查:
- 构建
violations
数组,标记违规记录。 - 使用滑动窗口计算每个连续7次考勤的违规次数总和。
- 若任何窗口总和超过3,返回
false
。
- 构建
示例测试
-
示例输入1:
输入:2 present present absent present present leaveearly present absent
输出:
true false
解释:- 第一个用例无缺勤且满足所有条件。
- 第二个用例缺勤两次,违反条件一。
-
测试用例2:
输入:1 late leaveearly
输出:
false
解释:相邻记录均为迟到/早退,违反条件二。 -
测试用例3:
输入:7 absent late late present present present present
输出:
false
解释:连续7次考勤中违规次数为3(absent + 2次late),满足条件三。
综合分析
-
时间复杂度:
- O(N),其中N为记录数。每个记录仅遍历两次(条件检查+滑动窗口)。
-
空间复杂度:
- O(N),存储考勤记录和违规标记数组。
-
正确性:
- 严格按题意分步骤检查三个条件,确保逻辑正确。
-
优势:
- 高效性:滑动窗口将条件三的时间复杂度优化为O(N)。
- 可读性:代码结构清晰,条件处理明确。
-
适用性:
- 完全支持题目约束(记录数≤1e5),满足时间和空间要求。
python
问题分析
题目要求判断员工的考勤记录是否符合出勤奖条件,需满足以下三个条件:
- 缺勤不超过一次(
absent
次数 ≤ 1); - 无连续迟到/早退(相邻记录不能同为
late
或leaveearly
); - 任意连续7次考勤中违规次数(缺勤、迟到、早退)不超过3次。
解题思路
- 条件一:统计所有记录中
absent
的次数,若超过1次直接判定失败。 - 条件二:遍历相邻记录,检查是否存在连续的
late
或leaveearly
。 - 条件三:使用滑动窗口检查所有长度为7的连续窗口,统计违规次数是否超过3次。
代码实现
import sys
def check_attendance(records):
# 条件一:缺勤次数不超过1次
absent_count = records.count('absent')
if absent_count > 1:
return False
# 条件二:检查相邻记录是否均为迟到/早退
for i in range(