如何解决如何有效地从多个组中找到范围的并集?
我正在创建一个公共时间范围的报告,其中所有给定的进程同时执行,我一直在做的是绘制图表并手动计算出来。现在我有更多的数据,绘制图形不是最佳解决方案,作为一名计算机工程师,我想以编程方式解决这个问题,使用最佳且高效的算法。
所以问题基本上是,
有 N
个进程,每个进程都有一个它已执行的时间范围列表,找到所有给定进程中所有公共时间间隔的最佳方法是什么。
示例:
假设有三个进程P1
、P2
、P3
,下面是该表给出了每个进程的执行时间信息:
-|---------|--------------------|-
| PROCESS | TIME OF EXECUTION |
-|---------|--------------------|-
| P1 | (0,4),(5,10) | **(updated from (0,1),10))
-|---------|--------------------|-
| P2 | (0,6),(1,8) |
-|---------|--------------------|-
| P3 | (3,10) |
-|---------|--------------------|-
如果我使用 Y-axis
中的每个过程和 X-axis
中的时间范围绘制图形,我可以得到如下所示的内容,并且公共范围以蓝色边框颜色突出显示。
从图中可以看出,输出/结果显然是 [ (3,8) ]
。
我正在寻找一种解决方案/算法来从给定的输入中推断出这些结果。我很感激能解决以下问题的答案:
- 适用于大量进程和每个进程的时间范围的通用理论解决方案。
- 这是Dynamic Programming问题吗?
- 在这种情况下,我可以使用任何算法吗?
- 是否类似于Largest Rectangle in Histogram问题?
解决方法
这可以通过维护前缀和并检查其计数来解决。
但在此之前,您需要进行一些基本的预处理。
对于进程的每次执行,都需要合并重叠的区间。
这是一个很常见的算法,你可以查一下。
所以,在这一步之后,你的输入变成了,
-|---------|--------------------|-
| PROCESS | TIME OF EXECUTION |
-|---------|--------------------|-
| P1 | (0,4),(5,10) |
-|---------|--------------------|-
| P2 | (0,8) |
-|---------|--------------------|-
| P3 | (3,10) |
-|---------|--------------------|-
对于 P2
,我们在这里所做的是将 (0,6) 和 (1,8) 合并为 (0,8)。
现在,下一步是计算前缀和的实际算法。
它的工作原理如下。
1. initialize a map
2. for each start_time,end_time.
map[start_time++] and map[[(end_time+1)]--]
(end_time+1)
的原因是因为进程一直运行到 end_time。在这个 end_time
之后,我们可以从我们的列表中删除它的计数。
所以,现在我们有了自己的价值观。
0 2
3 1
5 0
9 -1
11 -2
现在,我们可以开始计算前缀和了。
为此,我们初始化一个计数器 sum=0
。并按顺序排列地图的键。
num_processes=3
也被初始化了!。
`
at 0,val = 2,sum =2 (!=3) .(start=-1 and end =-1)
at 3,val = 1,sum =3 // intersection start (start=3,end=-1)
at 5,val = 0,sum =3 (remains same) // intersection end and start new one (add (3,4) and (start=5,end=-1)
at 9,val = -1,sum = 2 // intersection end (add 5,8) (start=-1 and end =-1)
at 11,val = -2,sum = 0 // (start=-1 and end =-1)
将 (3,8)
添加到最终结果中。
如果您有离散时间步长,您可以使用的 2 次传递方法是生成一个包含 N 个时间步长的数组,其中 N 是您正在观看的时间长度除以时间步长(即对于 1 毫秒的时间步长,离散时间)时间步长 10us 将有 N=101),然后遍历所有执行开始/停止对。每当进程开始时,将 1 添加到数组的该时间步长,每当进程停止时,从时间步长中减去 1。有些是负数,有些是正数,所有元素的总和应该为零。
接下来,创建一个整数,我们将其称为 process_count。它从 0 开始。您遍历数组,每次都将值添加到 process_count。 每当 process_count 等于将运行的进程总数时,您就找到了矩形。
伪代码:
//Create empty array to store value
array = zeroes(N)
//Assign each timestep the net change in number of running processes
for(tuple in process_runtimes):
array[tuple[0]] += 1
array[tuple[1]] -= 1
//Create array to store periods of all programs being on,tuple for individual periods and flag for state machine processing
all_on_periods = []
current_tuple = (0,0)
on_flag = 0
process_count = 0
//Iterate over array to calculate for each timestep the number of processes running.
for i in range(len(array)):
process_count += val[i]
//If all processes are running,create a tuple that tracks the beginning of the block where they are all running
if(process_count == total_processes and on_flag == 0):
on_flag = 1
current_tuple[0] = i
//Else,if all processes were running but aren't running any longer,enter the last timestamp they were all running on.
elseif(process_count == total_processes and on_flag == 0):
on_flag = 0
current_tuple[1] = i - 1
all_on_periods.append(current_tuple)
我不认为这是动态编程,但我不是这方面的权威。
虽然类似于最大直方图问题,但这也相当不同。这是关于二进制检查的并发性,而直方图问题是关于搜索矩形和比较大小。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。