我会尽可能地清楚。
我有一个有两次,开始和结束的事件。 (时间为24小时格式) 例如,此事件从8开始,到12结束。
通过此活动,我有一份工作时间表的人员列表。 这是一个例子:
现在,我需要知道在整个活动中我至少有多少人。
就我而言,它将 2 ,因为:
如果我用时间解释一下:
大多数情况下,该活动将有3人,但最低为2人。
如何使用算法获取此数字,我无法理解这一点。
我考虑过以分钟为单位转换时间(我不会在分钟之内),在事件时间设置范围(从8 * 60到12 * 60),并将每个人的存在添加为新范围,然后计算每分钟,有多少片(1片= 1人)。但我觉得这样效率不高,因为我必须将切片计算为4 * 60分钟:/(从8 - > 12)。
你会怎么做?
答案 0 :(得分:2)
获取人员编号i
的开始和结束时间,并将其命名为s_i
和e_i
。
将所有这些放在列表times
中。然后执行以下操作:
# start_time contains the start time of the event
# end_time contains the start time of the event
sort(times) # When doing this sort, make sure that if a s_i
# is at the same time as a e_j, put the s_i first.
current_number = number of people who're there at start_time
remove all times that match start_time from times
minimum_number = current_number
for time in times:
if time is an s_i: current_number += 1
if time is an e_i:
current_number -= 1
if current_number < minimum_number and time < end_time:
minimum_number = current_number
此操作的运行时间如下:
让n
为人数。
我们花费O(n lg n)
时间进行排序,因为我们只有2n
次排序。
O(n)
时间迭代时间,不断地工作。
总的来说,O(n lg n)
。请注意,此运行时间与其跨越的时间间隔完全无关,并且仅取决于您正在处理的人数。
这是sweep line algorithm的一种形式。我们横扫时间,只停留在感兴趣的点(s_i
和e_i
s。)
请注意,我们在s_i
之前对e_j
s进行排序的原因如下:
如果我们不这样做,那么想象我们有两个人:鲍勃在这里是8-10,爱丽丝在这里是10-12。那么,如果我们不仔细排序,我们可能会得到以下列表:
times = [(s_Bob, 8), (e_Bob, 10), (s_Alice, 10), (e_Alice, 12)]
如果我们这样排序,那么看起来好像鲍勃在10离开后没有人离开。但是,爱丽丝在那里,因为她同时到达。因此,为了防止这种情况,我们将它排序为开始时间在结束时间之前,如果是平局:
times = [(s_Bob, 8), (s_Alice, 10), (e_Bob, 10), (e_Alice, 12)]
答案 1 :(得分:0)
快速回答,或许每当有人开始/完成工作时都会更新人数?
例如,在t0,您将其设置为知道谁在那里。每隔一分钟或更好,每个请假/进入日期(已排序)都会记下当前新人数。
答案 2 :(得分:0)
如果您的活动中没有太多人,您可以去做
之类的事情minimum -> infinity
for each person in persons do:
intersections -> 0
for each other person in persons do:
if other person start time <= person start time
if other person end time >= person start time
intersections++
else if other person start time < person end time
intersections++
if intersections < minimum
minimum = intersections
答案 3 :(得分:0)
这是伪代码,因为没有语言标记。
有一个开始时间的排序列表,以及结束时间的排序列表
为零当前人员启动一个计数器
还有一个计数器,用于正无限的最小人数
将最近的时间作为活动的初始时间
一起浏览列表,选择第一个开始时间和第一个结束时间的早期
如果越早开始时间,请递增计数器并删除第一个开始时间 否则,越早结束时间,递减计数器并删除第一个结束时间
如果刚刚使用的时间与最近时间不同,请检查最低人数计数器(例如,如果有3个人同时进入,请等待更新最低人数计数器,直到处理所有三个人) 如果当前人员小于最低人数,请将最低人数设置为当前人员
更新最近的时间
重复,直到两个列表都为空
最低人数应该有你的答案
答案 4 :(得分:0)
我认为你的算法应该是这样设计的:
首先将事件的开始和结束时间添加到集 接下来,遍历您的成员构建 set 的开始和结束时间(设置防止重复)。 然后遍历集合中的项目,并针对集合中的每个元素检查每个成员,以查看他的开始时间是否> =并且结束时间是&gt;那么集合中的项目。有一个内部迭代的计数器来跟踪给定时间的人数,并且在两次迭代之外都有一个变量,用于跟踪给定时间内的最小人数。在伪代码中:
var set : set
var event_start : time = 8:00
var event_end : time = 12:00
set.add(event_start)
foreach(person in people)
set.add(person.start)
set.add(person.end)
var min : int = people.size
var time_of_min : time
foreach time in set
var num_people : int = 0
foreach person in people
if person.start >= time && person.end > time
num_people++
if num_people < min
min = num_people
time_of_min = time
// Handle the special case of the ending time
var num_people_at_end : int = 0
foreach person in people
if person.end == event_end
num_people_at_end++
if num_people_at_end < min
min = num_people_at_end
time_of_min = event_end