Skip to content

C. Clock Conversion - 题解

比赛与标签

比赛: Codeforces Round 937 (Div. 4) 标签: implementation, math 难度: *800

喵喵,时间魔法开始啦!

主人你好呀~!这道题就像一个可爱的时间魔法,需要我们把24小时制的时间,变成更常见的12小时制时间,的说!

举个例子,如果输入是 18:06,我们就要施展魔法,把它变成 06:06 PM

具体来说,题目会给我们一个 hh:mm 格式的24小时制时间字符串。我们的任务就是:

  1. 判断这个时间是上午(AM)还是下午(PM)。
  2. 把小时数转换成12小时制的格式。
  3. 分钟数保持不变。
  4. 最后按照 hh:mm AM/PM 的格式输出,注意小时数不足两位要补前导零哦!

本喵的解题思路喵~

要把这个时间魔法完美施展,我们可以一步一步来,就像猫咪走路一样,优雅又准确,喵~

第一步:分离小时和分钟

我们拿到的是一个像 "18:06" 这样的字符串。为了方便计算,我们需要把小时 "18" 和分钟 "06" 分开。

  • 小时部分 "18" 需要转换成数字,这样才能进行数学运算。
  • 分钟部分 "06" 不会改变,所以可以直接当成字符串保留下来,待会儿直接拼接到结果里就好啦。

第二步:判断是 AM 还是 PM

这是最简单的一步啦!根据24小时制的规则:

  • 如果小时数在 011 之间,那就是上午(AM)。
  • 如果小时数在 1223 之间,那就是下午(PM)。

所以,我们只需要检查一下刚刚得到的小时数 h 是不是小于 12 就可以啦!

第三步:转换小时数(最关键的魔法!)

这部分稍微有点小技巧,但难不倒聪明的我们,的说!我们来分析一下小时的转换规则:

  • 普通 AM 小时: 01:0011:59 -> 12小时制下还是 0111
  • 普通 PM 小时: 13:0023:59 -> 12小时制下是 0111。转换方法就是 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

所以,我们的统一规则就是:

  1. 计算 h % 12 得到新的小时数 h12
  2. 如果 h12 等于 0,就把它变成 12
  3. 否则,h12 就是我们想要的小时数。

这个方法是不是超级简洁又厉害呀?喵~

第四步:格式化输出

最后一步就是把我们准备好的材料拼接起来!

  • 转换后的小时数 h12
  • 冒号 :
  • 原始的分钟字符串 mm
  • 一个空格
  • 判断好的 AMPM

别忘了,如果 h12 是个位数(比如 6),要记得在前面补上一个 '0',让它变成 "06" 哦!

魔法代码的实现喵!

下面就是把我们的思路变成现实的代码啦,本喵加了详细的注释,方便主人理解每一句都在做什么!

cpp
#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 等)来存储当前时间的信息。使用的内存空间是固定的,不会因为输入的不同而改变,所以是常数空间复杂度。

本喵的小课堂时间!

这道题虽然是入门级,但里面的小技巧很实用哦!主人可以从中学到:

  1. 核心思想:对于有多种情况需要判断的问题,可以尝试寻找一个统一的数学公式或逻辑来简化代码,避免写冗长的 if-else 结构。
  2. 字符串处理substr() 用于截取子串,stoi() 用于将字符串转为整数。这是C++中处理字符串数字的常用组合技,一定要掌握呐!
  3. 数学技巧:善用取模运算符 %!它在处理周期性、循环性的问题时(比如时钟、星期)简直是神来之笔!
  4. 注意细节:千万不要忘记格式化输出,比如本题中的前导零。很多时候,成败就在这些小细节里,一不小心就会得到 WA (Wrong Answer) 的喵。

希望本喵的讲解对主人有帮助!只要多多练习,一定能成为算法大师的,加油喵~!(ฅ'ω'ฅ)

Released under the MIT License.