L2-2 老板的作息表
分数 25
全屏浏览题目
切换布局
作者 陈越
单位 浙江大学
新浪微博上有人发了某老板的作息时间表,表示其每天 4:30 就起床了。但立刻有眼尖的网友问:这时间表不完整啊,早上九点到下午一点干啥了?
本题就请你编写程序,检查任意一张时间表,找出其中没写出来的时间段。
输入格式:
输入第一行给出一个正整数 N,为作息表上列出的时间段的个数。随后 N 行,每行给出一个时间段,格式为:
hh:mm:ss - hh:mm:ss
其中 hh
、mm
、ss
分别是两位数表示的小时、分钟、秒。第一个时间是开始时间,第二个是结束时间。题目保证所有时间都在一天之内(即从 00:00:00 到 23:59:59);每个区间间隔至少 1 秒;并且任意两个给出的时间区间最多只在一个端点有重合,没有区间重叠的情况。
输出格式:
按照时间顺序列出时间表中没有出现的区间,每个区间占一行,格式与输入相同。题目保证至少存在一个区间需要输出。
输入样例:
8
13:00:00 - 18:00:00
00:00:00 - 01:00:05
08:00:00 - 09:00:00
07:10:59 - 08:00:00
01:00:05 - 04:30:00
06:30:00 - 07:10:58
05:30:00 - 06:30:00
18:00:00 - 19:00:00
输出样例:
04:30:00 - 05:30:00
07:10:58 - 07:10:59
09:00:00 - 13:00:00
19:00:00 - 23:59:59
代码长度限制
16 KB
Java (javac)
时间限制
900 ms
内存限制
128 MB
Python (python3)
时间限制
300 ms
内存限制
64 MB
其他编译器
时间限制
200 ms
内存限制
64 MB
我的答案:
一、信息
题目要求找出一个时间表中未列出的时间段。
二、分析
- 将所有时间段按开始时间排序。
- 对每一个时间段,比较其开始时间与上一个时间段的结束时间,以找出未列出的区间。
- 记录下这些区间并在最后输出。
三、算法设计
- 定义一个结构体Time,其中包含开始时间和结束时间。
- 将所有时间段存储在一个Time数组中。
- 对Time数组按开始时间进行排序。
- 遍历数组,对于每个时间段,比较其开始时间与上一个时间段的结束时间,记录下未列出的时间段。
四、代码实现(用C++)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct Time {
int start, end;
bool operator<(const Time &t) const {
return start < t.start;
}
};
int convert(const string &s) {
return stoi(s.substr(0, 2)) * 3600 + stoi(s.substr(3, 2)) * 60 + stoi(s.substr(6, 2));
}
string convertBack(int time) {
char buffer[10];
sprintf(buffer, "%02d:%02d:%02d", time / 3600, (time % 3600) / 60, time % 60);
return buffer;
}
int main() {
int N;
cin >> N;
vector<Time> times(N);
for(int i = 0; i < N; i++) {
string s, e, tmp;
cin >> s >> tmp >> e;
times[i].start = convert(s);
times[i].end = convert(e);
}
sort(times.begin(), times.end());
int lastTime = 0;
for(const auto &t : times) {
if(t.start - lastTime >= 1) {
cout << convertBack(lastTime) << " - " << convertBack(t.start) << endl;
}
lastTime = max(lastTime, t.end);
}
if(lastTime < 24 * 3600 - 1) {
cout << convertBack(lastTime) << " - " << "23:59:59" << endl;
}
return 0;
}
五、实现代码过程中可能遇到的问题
- 时间格式的转换可能会出现问题,要确保正确地从字符串格式转换为整数格式,反之亦然。
- 在对时间段进行排序后,需要确保正确地识别并输出所有的空白时间段。
- 注意处理时间段的边界情况,例如00:00:00和23:59:59。
正确答案:
一、信息 题目要求检查一个时间表,找出其中未列出的时间段。
二、分析
- 所有的时间段都存储在一个pair中,其中第一个元素是开始时间,第二个元素是结束时间。
- 时间段首先按照开始时间排序,这样我们可以从最早的时间段开始遍历,直到一天的结束。
三、算法设计
- 输入所有时间段,并存储在vector<pair<string,string>>中。
- 使用sort函数对所有时间段按开始时间进行排序。
- 从"00:00:00"开始,检查每一个时间段,看它是否与前一个时间段重叠或连续。
- 如果发现有空白时间段,即当前时间段的开始时间不等于上一个时间段的结束时间,则输出空白时间段。
- 遍历结束后,检查最后一个时间段的结束时间是否为"23:59:59"。如果不是,则输出从最后一个时间段的结束时间到"23:59:59"的空白时间段。
四、代码实现(用C++)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
int n;
cin >> n;
vector<pair<string, string>> intervals;
for(int i = 0; i < n; i++) {
string start, hyphen, end;
cin >> start >> hyphen >> end;
intervals.push_back({start, end});
}
sort(intervals.begin(), intervals.end());
string lastEnd = "00:00:00";
for(const auto &interval : intervals) {
if(interval.first != lastEnd) {
cout << lastEnd << " - " << interval.first << endl;
}
lastEnd = interval.second;
}
if(lastEnd != "23:59:59") {
cout << lastEnd << " - " << "23:59:59" << endl;
}
return 0;
}
五、实现代码过程中可能遇到的问题
- 时间段可能是连续或重叠的。例如,一个时间段从"08:00:00"到"09:00:00",接下来的时间段可能从"09:00:00"开始或更早。
- 如果不按照开始时间对时间段进行排序,就不能正确找出所有的空白时间段。
- 需要注意边界条件,即一天的开始时间"00:00:00"和结束时间"23:59:59"。
七、我错哪了?
我的错误主要在于处理连续时间段的逻辑。当考虑两个连续的时间段时,我仅比较了当前时间段的开始时间与前一个时间段的结束时间,而未正确处理以下几点:
- 如果一个时间段的结束时间超过下一个时间段的开始时间,应该取两者中较大的结束时间作为下一个时间段的结束时间。
- 对于多个相互重叠或连续的时间段,应连续处理它们,直到找到一个不连续的时间段或时间段结束。
正确代码简洁地处理了上述问题,特别是对于连续或重叠的时间段。我的代码没有正确处理这种情况,所以可能会在某些测试用例上失败。
八、学到了什么?
从这道题目中,你可以学到以下几点:
一、问题分析与解题技巧
- 数据结构的选择:如何使用
pair
和vector
来有效地存储和处理时间段信息。 - 排序的重要性:通过将时间段按开始时间排序,可以简化后续的处理过程,确保逻辑的连续性和正确性。
- 边界条件的处理:如何处理一天的开始和结束时间,以确保所有的空白时间段都被考虑到。
二、编程技能与实践
- STL的应用:如何使用C++标准模板库中的
sort
函数和vector
容器来简化编程任务。 - 字符串处理:如何处理和比较时间格式的字符串,以及如何进行格式化输出。
三、问题解决的策略与方法
- 逐步解决问题:首先处理输入数据,然后进行排序,接着逐步遍历时间段以找出所有的空白时间段。
- 利用已有的知识和技能:根据已知的数据结构和算法,设计一个简单且高效的解决方案。
四、反思与优化
- 简洁性与效率:有时,简单直接的方法可能比复杂的算法更加有效。例如,正确答案比我最初的答案更简洁且更易于理解。
- 测试与验证:在解决问题时,重要的是进行充分的测试,确保答案在各种情况下都是正确的。
五、通用性与应用性
- 通用问题解决方法:这种类型的问题——找出一系列区间中的空白区间——在实际应用中很常见,例如在日程安排或资源分配中。
- 学习与实践的结合:通过实际的编程问题,加深对某些编程概念或技巧的理解,这有助于你在未来的编程任务中更加熟练和自信。
总的来说,这道题目不仅提供了一个具体的编程挑战,而且也为我提供了一个反思和学习编程方法和策略的机会。