#P3021. 日志排序(100分)
-
1000ms
Tried: 232
Accepted: 71
Difficulty: 3
所属公司 :
华为od
-
算法标签>排序算法
日志排序(100分)
题面描述
运维工程师采集到某产品线网运行一天产生的日志,共有 n 条,需根据日志时间先后顺序对其进行排序。日志时间格式为 H:M:S.N,其中 H 表示小时(0~23),M 表示分钟(0~59),S 表示秒(0~59),N 表示毫秒(0~999)。时间可能未补全,例如 01:01:01.001 可能表示为 1:1:1.1。输入的第一行为日志条数 n(1≤n≤100000),接下来 n 行输入时间。输出时需按时间升序排序,且若时间相同,则保持输入顺序。
思路
-
解析时间字符串:将每个时间字符串按照
H:M:S.N的格式分割,并将各部分转换为整数。 -
计算总毫秒数:为了方便比较,将每个时间转换为总毫秒数,计算公式为:
total_ms = H * 3600000 + M * 60000 + S * 1000 + N -
保持稳定排序:由于需要在时间相同的情况下保持输入顺序,选择稳定的排序算法。C++ 中的
stable_sort函数能够满足这一要求。 -
存储原始时间字符串:为了在排序后输出原始格式的时间,需要在存储总毫秒数的同时保存原始的时间字符串。
-
排序并输出:根据总毫秒数进行排序,排序完成后按顺序输出原始时间字符串。
cpp
#include <bits/stdc++.h>
using namespace std;
// 定义一个结构体来存储时间的总毫秒数和原始时间字符串
struct Log {
long long total_ms; // 总毫秒数
string original; // 原始时间字符串
};
// 函数用于解析时间字符串并计算总毫秒数
long long parseTime(const string& timeStr) {
int H = 0, M = 0, S = 0, N = 0;
int pos1 = timeStr.find(':');
H = stoi(timeStr.substr(0, pos1));
int pos2 = timeStr.find(':', pos1 + 1);
M = stoi(timeStr.substr(pos1 + 1, pos2 - pos1 - 1));
int pos3 = timeStr.find('.', pos2 + 1);
S = stoi(timeStr.substr(pos2 + 1, pos3 - pos2 - 1));
// 如果没有小数点,毫秒为0
if (pos3 != string::npos) {
string msStr = timeStr.substr(pos3 + 1);
N = stoi(msStr);
}
return static_cast<long long>(H) * 3600000 + static_cast<long long>(M) * 60000
+ static_cast<long long>(S) * 1000 + N;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(NULL);
int n;
cin >> n;
vector<Log> logs(n);
for(int i = 0; i < n; ++i){
cin >> logs[i].original;
logs[i].total_ms = parseTime(logs[i].original);
}
// 稳定排序,按总毫秒数升序
stable_sort(logs.begin(), logs.end(), [&](const Log &a, const Log &b) -> bool{
return a.total_ms < b.total_ms;
});
// 输出排序后的原始时间字符串
for(auto &log : logs){
cout << log.original << "\n";
}
return 0;
}
python
import sys
def parse_time(time_str):
parts = time_str.strip().split(':')
H = int(parts[0])
M = int(parts[1])
S, N = 0, 0
if '.' in parts[2]:
S_part, N_part = parts[2].split('.')
S = int(S_part)
N = int(N_part)
else:
S = int(parts[2])
total_ms = H * 3600000 + M * 60000 + S * 1000 + N
return total_ms
def main():
input = sys.stdin.read().splitlines()
n = int(input[0])
logs = []
for i in range(1, n+1):
time_str = input[i]
total_ms = parse_time(time_str)
logs.append( (total_ms, i, time_str) )
# 使用稳定的排序,首先按总毫秒数
logs.sort(key=lambda x: x[0])
for log in logs:
print(log[2])
if __name__ == "__main__":
main()
java
import java.io.*;
import java.util.*;
public class Main {
// 定义一个类来存储时间的总毫秒数和原始时间字符串以及输入顺序
static class Log {
long totalMs;
String original;
int index; // 输入顺序
Log(long totalMs, String original, int index){
this.totalMs = totalMs;
this.original = original;
this.index = index;
}
}
// 函数用于解析时间字符串并计算总毫秒数
static long parseTime(String timeStr){
String[] parts = timeStr.split(":");
int H = Integer.parseInt(parts[0]);
int M = Integer.parseInt(parts[1]);
int S = 0, N = 0;
if(parts[2].contains(".")){
String[] secParts = parts[2].split("\\.");
S = Integer.parseInt(secParts[0]);
N = Integer.parseInt(secParts[1]);
}
else{
S = Integer.parseInt(parts[2]);
}
return (long)H * 3600000 + (long)M * 60000 + (long)S * 1000 + N;
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
List<Log> logs = new ArrayList<>();
for(int i = 0; i < n; i++){
String timeStr = br.readLine();
long totalMs = parseTime(timeStr);
logs.add(new Log(totalMs, timeStr, i));
}
// 使用稳定的排序,首先按总毫秒数,保持输入顺序
Collections.sort(logs, new Comparator<Log>(){
public int compare(Log a, Log b){
if(a.totalMs != b.totalMs){
return Long.compare(a.totalMs, b.totalMs);
}
else{
return Integer.compare(a.index, b.index);
}
}
});
// 输出排序后的原始时间字符串
StringBuilder sb = new StringBuilder();
for(Log log : logs){
sb.append(log.original).append("\n");
}
System.out.print(sb.toString());
}
}
题目描述
运维工程师采集到某产品线网运行一天产生的日志 n 条,现需根据日志时间先后顺序对日志进行排序,日志时间格式为 H:M:S.N 。
H 表示小时(0~23)
M 表示分钟(0~59)
S 表示秒(0~59)
N 表示毫秒(0~999)
时间可能并没有补全,也就是说,01:01:01.001 也可能表示为 1:1:1.1 。
输入描述
第一行输入一个整数 n 表示日志条数,1<=n<=100000 ,接下来 n 行输入 n 个时间。
输出描述
按时间升序排序之后的时间,如果有两个时间表示的时间相同,则保持输入顺序。
样例1
输入
2
01:41:8.9
1:1:09.211
输出
1:1:09.211
01:41:8.9
样例2
输入
3
23:41:08.023
1:1:09.211
08:01:22.0
输出
1:1:09.211
08:01:22.0
23:41:08.023
样例3
输入
2
22:41:08.023
22:41:08.23
输出
22:41:08.023
22:41:08.23
说明
两个时间表示的时间相同,保持输入顺序