在我的小问题中,我有n个用户和m个设备(m和n~50000)。一个用户一次只能使用一个设备。
我有这种格式的记录列表[ u,e,t ],其中 t (时间)按升序排序。每条记录都意味着用户 u 在 t 时使用 e 设备。记录数量约为5亿。假设具有相同 u 和 e 的两个最近记录表示 u 连续使用 e 。例如:
1, 2, 1
3, 4, 1
1, 2, 3
1, 2, 4
1, 2, 5
2, 6, 6
3, 2, 6
3, 2, 8
意味着用户1使用1到5的设备2.
我想要做的是从这个列表中,以这种格式推断换班时间:[ u,e,st,et ]这意味着用户 u 使用设备 e 从开始时间 st 到结束时间 et 。
样本数据的结果为:
1, 2, 0, 5
3, 4, 0, 6
3, 2, 6, 8
(假设时间从0开始并以max(t)结束,并且当第一次看到一对(u,e)时,u从0开始就已经开始使用e。类似于最后的记录。 )
鉴于大名单(5亿条记录)但m和n足够小,我怎样才能最有效地做到这一点?
@Edit:可能的数据不一致:
1:如果样本数据中只有1个记录(因此没有结束时间),例如[2,6,6]的情况:
---如果这是用户2和设备6出现在数据集中的唯一时间,则忽略数据点
---如果在该记录之后,用户2使用另一台设备,比如7比10,那么2比6使用6比5
---如果在该记录之后,设备6被另一个用户使用,比如10比11,那么2比6使用6比11。
答案 0 :(得分:2)
定义两个结构(我知道这是Java,但让我们假设一个通用算法):
struct user_record {
int machine_idx;
int start_time;
}
struct machine_record {
int user_idx;
int start_time;
}
鉴于用户不能同时使用多个设备,您可以创建一个user_record
s的数组/向量,每个用户一个(你说这是~50k,所以这个应该是易处理的),以及machine_record
s的数组/向量,每台机器一个。将所有元素'idx
成员初始化为-1(表示当前未激活)。
然后,每次遇到输入记录时,请检查idx
和user_record
数组中相应machine_record
字段的状态。有三种可能性:
start_time
。idx
字段重置为-1。 / LI>
这是 O(N)时间(其中 N 是输入记录的数量)。
注意:输出将按结束时间排序。
答案 1 :(得分:1)
@ Oli-Charlesworth走在正确的轨道上,但细节不足。
你需要的是有两个向量,一个用于用户,一个用于机器。机器指向用户。用户指向机器。其中一个向量,无论哪个向我使用,都必须跟踪它们第一次关联,以及它们最后一次关联。
初始化所有内容,使每个用户指向-1(无机器),每台机器指向-1(无用户)。以下是如何处理记录的伪代码:
for (user, machine, time) in records:
# By user.machine I mean look up the machine the user currently points at
if user.machine <> machine:
output_record_and_clear(user)
if machine.user <> user:
output_record_and_clear(machine.user)
user.machine = machine
machine.user = user
user.start_time = time
user.end_time = time
def output_record_and_clear (user):
if -1 <> user.machine and user.start_time < user.end_time:
emit(user, user.machine, user.start_time, user.end_time)
user.machine.user = -1
user.machine = -1
答案 2 :(得分:0)
我会通过用户或机器对文件进行排序来解决这个问题(因为它是一对一的,它应该没关系)然后按时间然后问题很简单,只需逐行排列并输出班次
您还可以在内存中逐行执行此操作,方法是保留正在使用的计算机的哈希表以及上次使用它们时,再次看到计算机时,输出使用的时间并更新表。只有50,000台机器,这应该可以正常工作。