目录
题目
思路
Code
题目
题目内容:
在日常开发中,用户输入的日期格式五花八门。现需要你编写一个程序,能够识别多种日期格式,将其统一输出为 yyyy-mm-dd 格式,并按日期递增顺序排列。
输入为字符串数组。字符串格式类型中,月和日可能补零也可能不补零。
支持斜杠分隔格式,例如 2022/01/01 或 2022/1/1。
支持横杠分隔格式,例如 2022-01-01 或 2022-1-1。
合法年份范围为 1000 到 2100。
输入可能包含非法格式,非斜杠分隔、非横杠分隔、横杠和斜杠混合的内容均为非法格式,非法格式忽略。
不同格式的输入可能解析为同一日期,相同日期只输出一次。
输入数组长度在 1 到 200 范围内,单个字符串长度不超过 50。
需要判断日期合法性,例如月份不能超过 12,二月平年有 28 天,闰年有 29 天。
年份能被 4 整除且不能被 100 整除,或者能被 400 整除都为闰年,否则都是平年。
输入描述:
输入为一行字符串数组,多个日期字符串用英文逗号分隔。
输出描述:
按日期递增顺序输出字符串数组,每个日期字符串输出 yyyy-mm-dd 格式的日期。月份和日期不足两位补前导零。
若所有输入均非法,则输出仅包含一个元素且元素为 NULL 的字符串数组。
输入判定规则中,包含斜杠时按 yyyy/mm/dd 解析,包含横杠时按 yyyy-mm-dd 解析;混合分隔符会因为字段包含非数字而判为非法。
样例 1
输入:
2022/01/01,2022-1-1,20220101,1640995200,2022/1/1,2022-01-01,2022-12-31,1641081600输出:
2022-01-01,2022-12-31说明:
多个输入会解析为 2022-01-01,去重后再和 2022-12-31 一起升序输出。
样例 2
输入:
2021/02/29,2021/02-20输出:
NULL说明:
2021 年 2 月没有 29 日,混合分隔符也非法,因此没有合法日期。
样例 3
输入:
1970/1/1输出:
1970-01-01说明:
1970/1/1 转换后为 1970-01-01。
思路
整体思路:这道题可以分成解析、校验、去重排序三个部分。
第一步:逐个处理输入中的日期字符串,先判断它使用的是斜杠还是横杠作为分隔符。
如果一个字符串同时包含斜杠和横杠,或者两种分隔符都没有,就不属于题目支持的格式,直接忽略。
第二步:按照确定好的分隔符切分字符串。
合法日期必须刚好切成年、月、日三段;如果不是三段,或者某一段为空、包含非数字字符,就说明这个日期非法。
第三步:把年、月、日转成整数后继续做日期合法性校验。
年份必须在 1000 到 2100 之间,月份必须在 1 到 12 之间,这两个条件先判断,避免后面查询月份天数时出错。
第四步:判断日期天数是否合法。
普通月份可以直接按月份查最大天数,二月需要额外判断闰年:能被 4 整除且不能被 100 整除,或者能被 400 整除,才是闰年。
例如 2024 年 2 月 29 日合法,但 2021 年 2 月 29 日非法。
第五步:把合法日期统一格式化为 yyyy-mm-dd。
月份和日期不足两位时要补前导零,例如 2022/1/1 要转换为 2022-01-01。
第六步:用集合去重。
同一个日期可能有多种写法,例如 2022/1/1 和 2022-01-01,它们最终都表示同一天,只输出一次即可。
第七步:对去重后的日期字符串排序。
yyyy-mm-dd 这种格式的年月日从大到小排列,所以按字符串升序排序时,结果就等价于按真实日期递增排序。
如果最后集合为空,说明没有任何合法日期,按题目要求输出 NULL。
Code
import sys def is_leap(year): # 闰年规则只影响二月的最大天数。 return (year % 4 == 0 and year % 100 != 0) or year % 400 == 0 def days_in_month(year, month): days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] if month == 2 and is_leap(year): return 29 return days[month - 1] def parse_date(text): has_slash = "/" in text has_dash = "-" in text # 混合分隔符或没有分隔符都不符合题目支持的格式。 if has_slash == has_dash: return None delimiter = "/" if has_slash else "-" parts = text.split(delimiter) if len(parts) != 3: return None if any(part == "" or not part.isdigit() for part in parts): return None year, month, day = map(int, parts) # 年、月、日逐层校验,避免月份非法时访问天数数组越界。 if year < 1000 or year > 2100: return None if month < 1 or month > 12: return None if day < 1 or day > days_in_month(year, month): return None return f"{year:04d}-{month:02d}-{day:02d}" def main(): text = sys.stdin.read().strip() dates = text.split(",") if text != "" else [""] normalized = set() for item in dates: parsed = parse_date(item.strip()) if parsed is not None: # 集合负责去重,同一天不同写法只保留一次。 normalized.add(parsed) if not normalized: print("NULL") else: print(",".join(sorted(normalized))) if __name__ == "__main__": main()JS
const fs = require("fs"); const line = fs.readFileSync(0, "utf8").trim(); function isLeap(year) { // 闰年规则只影响二月最大天数。 return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; } function daysInMonth(year, month) { const days = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; if (month === 2 && isLeap(year)) { return 29; } return days[month - 1]; } function parseDate(text) { const hasSlash = text.includes("/"); const hasDash = text.includes("-"); // 只允许单一分隔符,混用或无分隔符都非法。 if (hasSlash === hasDash) { return null; } const delimiter = hasSlash ? "/" : "-"; const parts = text.split(delimiter); if (parts.length !== 3) { return null; } for (const part of parts) { if (!/^\d+$/.test(part)) { return null; } } const year = Number(parts[0]); const month = Number(parts[1]); const day = Number(parts[2]); // 先校验年月范围,再检查当月最大天数。 if (year < 1000 || year > 2100 || month < 1 || month > 12) { return null; } if (day < 1 || day > daysInMonth(year, month)) { return null; } return `${String(year).padStart(4, "0")}-${String(month).padStart(2, "0")}-${String(day).padStart(2, "0")}`; } const seen = new Set(); const items = line === "" ? [""] : line.split(","); for (const item of items) { const parsed = parseDate(item.trim()); if (parsed !== null) { // Set 负责去重,排序在输出前统一处理。 seen.add(parsed); } } if (seen.size === 0) { process.stdout.write("NULL"); } else { process.stdout.write(Array.from(seen).sort().join(",")); }【华为od机试真题Python+JS+Java+Go合集】【超值优惠】:Py/JS/Java/Go合集
【华为od机试真题Python】:Python真题题库
【华为od机试真题JavaScript】:JavaScript真题题库
【华为od机试真题Java&Go】:Java&Go真题题库
【华为od机试真题C++】:C++真题题库
【华为od机试真题C语言】:C语言真题题库
【华为od面试手撕代码题库】:面试手撕代码题库
【华为od机试面试交流群】【文章底部有二维码链接,可扫码加交流群】
华为OD机试:二本院校有机会吗? 有机会,但不大,大神除外!机考分数越高越好,所以需要提前刷题。机考通过后,如果没有收到面试邀请,也不要着急,非目标院校面试邀请发的时间比较晚。非目标院校今年有点难,机试至少要考到350分,所以需要疯狂刷题,华为OD机考是有题库的,最好在考前完所有题库题目。华为OD机试:跨专业可以参加华为OD可以,但是如果你的本科院校比较差,上岸概率不大。华为OD机试:华为OD简历被锁定机试通过,性格测试也通过,但是没人联系面试,发现简历被锁定。此时需要主动去联系HR。让他帮助你查询原因。