题解 | #魔法相册的重复记忆#
魔法相册的重复记忆
https://www.nowcoder.com/practice/878ab473951d4e3a94bdf965da751d97
题目链接
题目描述
小红正在整理自己的 本魔法相册,她发现有些珍贵的记忆(照片)由于备份原因,同时出现在了多本相册中。每张照片由一个唯一的标识符
和一个时间戳
组成。在一个相册内部,所有照片的
互不相同;但在不同的相册之间,可能存在相同的照片。已知相同的
总是对应相同的时间戳
。小红需要找出所有在超过一本相册中出现过的照片,并统计它们在所有相册中出现的总次数。请将这些重复的照片按照时间戳
从小到大排序后输出。
解题思路
-
数据读取与统计: 由于输入数据中每行包含的照片数量
不固定,我们需要按行读取输入。对于每一行,解析出若干对
。 我们需要统计每个
出现的次数,并记录其对应的时间戳
。由于题目保证相同的
对应相同的时间戳,我们只需要在第一次遇到该
时记录
即可。
-
筛选重复照片: 遍历统计结果,筛选出出现次数
的
。
-
排序与输出: 将筛选出的重复照片(包含
、
和
)存入列表中。按照时间戳
对列表进行升序排序。最后依次输出
和
。
代码
#include <iostream>
#include <vector>
#include <map>
#include <string>
#include <sstream>
#include <algorithm>
using namespace std;
// 定义结构体存储照片信息
struct Photo {
int id;
int t;
int count;
};
// 排序规则:按时间戳升序
bool compare(const Photo& a, const Photo& b) {
return a.t < b.t;
}
int main() {
int n;
// 读取相册数量
cin >> n;
string dummy;
getline(cin, dummy); // 消耗掉第一行后的换行符
map<int, int> counts; // 存储 ID 出现的次数
map<int, int> timestamps; // 存储 ID 对应的时间戳
for (int i = 0; i < n; ++i) {
string line;
getline(cin, line);
stringstream ss(line);
int id, t;
// 每两个整数为一组 (ID, T)
while (ss >> id >> t) {
counts[id]++;
timestamps[id] = t;
}
}
vector<Photo> result;
for (auto const& [id, count] : counts) {
if (count > 1) {
result.push_back({id, timestamps[id], count});
}
}
// 排序
sort(result.begin(), result.end(), compare);
// 格式化输出
for (int i = 0; i < result.size(); ++i) {
cout << result[i].id << " " << result[i].count << (i == result.size() - 1 ? "" : " ");
}
cout << endl;
return 0;
}
import java.util.*;
public class Main {
// 存储照片信息的类
static class Photo {
int id;
int t;
int count;
Photo(int id, int t, int count) {
this.id = id;
this.t = t;
this.count = count;
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 读取相册数量
int n = Integer.parseInt(sc.nextLine());
Map<Integer, Integer> counts = new HashMap<>(); // ID 频次统计
Map<Integer, Integer> timestamps = new HashMap<>(); // ID 时间戳映射
for (int i = 0; i < n; i++) {
String line = sc.nextLine();
String[] parts = line.trim().split("\\s+");
for (int j = 0; j < parts.length; j += 2) {
int id = Integer.parseInt(parts[j]);
int t = Integer.parseInt(parts[j + 1]);
counts.put(id, counts.getOrDefault(id, 0) + 1);
timestamps.put(id, t);
}
}
List<Photo> result = new ArrayList<>();
for (Map.Entry<Integer, Integer> entry : counts.entrySet()) {
if (entry.getValue() > 1) {
int id = entry.getKey();
result.add(new Photo(id, timestamps.get(id), entry.getValue()));
}
}
// 按时间戳排序
result.sort((a, b) -> a.t - b.t);
// 输出结果
for (int i = 0; i < result.size(); i++) {
System.out.print(result.get(i).id + " " + result.get(i).count + (i == result.size() - 1 ? "" : " "));
}
System.out.println();
}
}
def solve():
# 读取相册数量
n = int(input())
counts = {} # ID 频次统计
timestamps = {} # ID 时间戳映射
for _ in range(n):
line_data = input().split()
# 每两个整数为一组 (ID, T)
for i in range(0, len(line_data), 2):
photo_id = int(line_data[i])
t = int(line_data[i + 1])
counts[photo_id] = counts.get(photo_id, 0) + 1
timestamps[photo_id] = t
res_list = []
for photo_id, count in counts.items():
if count > 1:
res_list.append((photo_id, count, timestamps[photo_id]))
# 按时间戳 T 升序排序
res_list.sort(key=lambda x: x[2])
output = []
for photo_id, count, t in res_list:
output.append(str(photo_id))
output.append(str(count))
print(" ".join(output))
solve()
算法及复杂度
- 算法:哈希表(映射)统计 + 排序
- 时间复杂度:
。其中
是相册数,
是每本相册平均照片数。读取和统计需要
,排序最坏需要
。
- 空间复杂度:
。需要存储所有不同照片的
、出现次数及其时间戳。
查看9道真题和解析