C. Clock Conversion - 题解
比赛与标签
比赛: Codeforces Round 937 (Div. 4) 标签: implementation, math 难度: *800
喵喵,时间魔法开始啦!
主人你好呀~!这道题就像一个可爱的时间魔法,需要我们把24小时制的时间,变成更常见的12小时制时间,的说!
举个例子,如果输入是 18:06
,我们就要施展魔法,把它变成 06:06 PM
。
具体来说,题目会给我们一个 hh:mm
格式的24小时制时间字符串。我们的任务就是:
- 判断这个时间是上午(AM)还是下午(PM)。
- 把小时数转换成12小时制的格式。
- 分钟数保持不变。
- 最后按照
hh:mm AM/PM
的格式输出,注意小时数不足两位要补前导零哦!
本喵的解题思路喵~
要把这个时间魔法完美施展,我们可以一步一步来,就像猫咪走路一样,优雅又准确,喵~
第一步:分离小时和分钟
我们拿到的是一个像 "18:06"
这样的字符串。为了方便计算,我们需要把小时 "18"
和分钟 "06"
分开。
- 小时部分
"18"
需要转换成数字,这样才能进行数学运算。 - 分钟部分
"06"
不会改变,所以可以直接当成字符串保留下来,待会儿直接拼接到结果里就好啦。
第二步:判断是 AM 还是 PM
这是最简单的一步啦!根据24小时制的规则:
- 如果小时数在
0
到11
之间,那就是上午(AM)。 - 如果小时数在
12
到23
之间,那就是下午(PM)。
所以,我们只需要检查一下刚刚得到的小时数 h
是不是小于 12
就可以啦!
第三步:转换小时数(最关键的魔法!)
这部分稍微有点小技巧,但难不倒聪明的我们,的说!我们来分析一下小时的转换规则:
- 普通 AM 小时:
01:00
到11:59
-> 12小时制下还是01
到11
。 - 普通 PM 小时:
13:00
到23:59
-> 12小时制下是01
到11
。转换方法就是h - 12
。 - 特殊情况 1:
00:00
(午夜) -> 12小时制下是12:00 AM
。 - 特殊情况 2:
12:00
(中午) -> 12小时制下是12:00 PM
。
如果用一堆 if-else
来写会很麻烦。本喵发现了一个超级优雅的数学魔法:取模运算 %
!
我们来试试 h % 12
会发生什么:
13 % 12 = 1
18 % 12 = 6
23 % 12 = 11
PM的小时完美转换了!1 % 12 = 1
11 % 12 = 11
AM的小时(除了0点)也完美保持不变!
现在只剩下两个捣蛋鬼:00
点和 12
点。
00 % 12 = 0
12 % 12 = 0
看呐!它们俩取模后都变成了0
!而在12小时制里,它们都应该显示为12
。
所以,我们的统一规则就是:
- 计算
h % 12
得到新的小时数h12
。 - 如果
h12
等于0
,就把它变成12
。 - 否则,
h12
就是我们想要的小时数。
这个方法是不是超级简洁又厉害呀?喵~
第四步:格式化输出
最后一步就是把我们准备好的材料拼接起来!
- 转换后的小时数
h12
- 冒号
:
- 原始的分钟字符串
mm
- 一个空格
- 判断好的
AM
或PM
别忘了,如果 h12
是个位数(比如 6
),要记得在前面补上一个 '0'
,让它变成 "06"
哦!
魔法代码的实现喵!
下面就是把我们的思路变成现实的代码啦,本喵加了详细的注释,方便主人理解每一句都在做什么!
#include <iostream>
#include <string>
using namespace std;
int main() {
// t是测试用例的数量,先读进来喵~
int t;
cin >> t;
while (t--) {
// 读入 "hh:mm" 格式的时间字符串
string s;
cin >> s;
// 用 substr 截取前两位作为小时,再用 stoi 把它变成整数,方便计算!
int h = stoi(s.substr(0, 2));
// 分钟部分从第3个位置开始(下标从0算哦),截取两位。它不用变,所以还是字符串就好啦。
string m = s.substr(3, 2);
// 判断是上午还是下午。这里用了一个超可爱的三元运算符!
// 如果小时h小于12,就是AM,否则就是PM。一行就搞定了判断,好厉害的说!
string period = (h < 12) ? "AM" : "PM";
// 这就是我们刚才分析的核心魔法!用取模运算来转换小时数。
int h12 = h % 12;
// 处理 00:xx 和 12:xx 的特殊情况。
// 取模后等于0的,都应该显示为12点。
if (h12 == 0) {
h12 = 12;
}
// 为了美观和符合题目要求,如果小时是一位数,就在前面补一个'0',喵~
if (h12 < 10) {
cout << '0';
}
// 最后把所有部分拼起来,加上冒号和空格,完美输出!
cout << h12 << ':' << m << ' ' << period << '\n';
}
return 0;
}
时空消耗分析喵
- 时间复杂度: O(T) 的说。 对于每个测试用例,我们都执行了固定次数的字符串操作和算术运算,这些操作的时间消耗是常数级别的。如果有 T 个测试用例,总时间就和 T 成正比啦。
- 空间复杂度: O(1) 的说。 在每次循环中,我们只用了几个变量(
s
,h
,m
,period
等)来存储当前时间的信息。使用的内存空间是固定的,不会因为输入的不同而改变,所以是常数空间复杂度。
本喵的小课堂时间!
这道题虽然是入门级,但里面的小技巧很实用哦!主人可以从中学到:
- 核心思想:对于有多种情况需要判断的问题,可以尝试寻找一个统一的数学公式或逻辑来简化代码,避免写冗长的
if-else
结构。 - 字符串处理:
substr()
用于截取子串,stoi()
用于将字符串转为整数。这是C++中处理字符串数字的常用组合技,一定要掌握呐! - 数学技巧:善用取模运算符
%
!它在处理周期性、循环性的问题时(比如时钟、星期)简直是神来之笔! - 注意细节:千万不要忘记格式化输出,比如本题中的前导零。很多时候,成败就在这些小细节里,一不小心就会得到 WA (Wrong Answer) 的喵。
希望本喵的讲解对主人有帮助!只要多多练习,一定能成为算法大师的,加油喵~!(ฅ'ω'ฅ)