题解:学而思编程 最年长的人
【题目来源】
学而思编程:最年长的人
【题目描述】
小猴班上有 \(n\) 名同学,小猴作为班长知道班上每名同学的出生日期。现在小猴想要知道班上最大年龄的同学的出生日期是多少,请你帮助小猴完成这个任务。
【输入】
第一行一个正整数 \(n\);
第二行到第 \(n+1\) 行,每行三个整数 \(a,b,c\),表示每位同学的出生日期(即 \(a\) 年 \(b\) 月 \(c\) 日出生)。
【输出】
一行三个整数 \(y,m,d\),表示年龄最大同学的出生日期,\(m,d\) 如果是一位数时需要有前导 \(0\)。
【输入样例】
3
2008 01 02
2010 10 20
2010 11 11
【输出样例】
2008 01 02
【核心思想】
-
问题分析:给定 \(n\) 名同学的出生日期,求年龄最大(即出生日期最早)的同学的出生日期。这是一个日期比较 + 贪心更新问题,关键在于按年、月、日的优先级依次比较,找到最早的日期。
-
算法选择:
- 初始化最新日期:将当前最优日期设为一个较晚的日期(如 \(2021\) 年 \(12\) 月 \(31\) 日)
- 逐日期比较:按年、月、日的优先级依次比较,更新最早日期
-
关键步骤:
- 初始化:
- 读取 \(n\)
y = 2021, m = 12, d = 31:初始化为较晚日期
- 逐日期比较(遍历 \(i\) 从 \(1\) 到 \(n\)):
- 读取 \(a, b, c\)(年、月、日)
- 若 \(a > y\):
continue(当前日期更晚,不更新) - 否则若 \(a < y\):更新
y = a, m = b, d = c(当前日期更早) - 否则(年份相同):
- 若 \(b > m\):
continue(月份更晚,不更新) - 否则若 \(b < m\):更新
m = b, d = c(月份更早) - 否则(年月相同):
d = min(d, c)(取更早的日)
- 若 \(b > m\):
- 格式化输出:
printf("%d %02d %02d", y, m, d):月份和日期保持两位,不足补前导零
- 初始化:
-
时间/空间复杂度:
- 时间复杂度:\(O(n)\),线性遍历 \(n\) 个日期
- 空间复杂度:\(O(1)\),仅需存储当前最优日期
-
日期比较的核心思想:
- 字典序比较:日期按年、月、日优先级依次比较,与字符串字典序比较同理,先比高位再比低位
- 贪心更新:遇到更早的日期立即更新,保证遍历结束后得到全局最早日期
- 初始化策略:初始化为一个足够晚的日期(晚于所有可能的输入),确保第一个日期必然更新
- 格式化输出:
%02d确保月份和日期为两位数,不足时自动补前导零 - 适用于"多关键字比较 + 极值查找"类问题,按优先级逐层比较是标准方法
【算法标签】
模拟
【代码详解】
#include <bits/stdc++.h>
using namespace std;
int n; // 输入日期的数量
int main()
{
cin >> n; // 输入日期数量
// 初始化最新日期为2021年12月31日
int y = 2021; // 年份
int m = 12; // 月份
int d = 31; // 日期
// 处理每个输入的日期
for (int i = 1; i <= n; i++)
{
int a, b, c; // 当前输入的日期:a=年, b=月, c=日
cin >> a >> b >> c;
// 比较逻辑:寻找最早的日期
if (a > y) // 如果当前年份比最新日期晚
{
continue; // 跳过,不更新
}
else if (a < y) // 如果当前年份比最新日期早
{
y = a; // 更新年份
m = b; // 更新月份
d = c; // 更新日期
}
else // 年份相同
{
if (b > m) // 如果当前月份比最新日期晚
{
continue; // 跳过,不更新
}
else if (b < m) // 如果当前月份比最新日期早
{
m = b; // 更新月份
d = c; // 更新日期
}
else // 年份和月份都相同
{
d = min(d, c); // 取更早的日期
}
}
}
// 输出最早日期,月份和日期用两位数字表示
printf("%d %02d %02d\n", y, m, d);
return 0; // 程序正常结束
}
【运行结果】
3
2008 01 02
2010 10 20
2010 11 11
2008 01 02
浙公网安备 33010602011771号