微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何有效地从多个组中找到范围的并集?

如何解决如何有效地从多个组中找到范围的并集?

我正在创建一个公共时间范围的报告,其中所有给定的进程同时执行,我一直在做的是绘制图表并手动计算出来。现在我有更多的数据,绘制图形不是最佳解决方案,作为一名计算机工程师,我想以编程方式解决这个问题,使用最佳且高效的算法。

所以问题基本上是,

N 个进程,每个进程都有一个它已执行的时间范围列表,找到所有给定进程中所有公共时间间隔的最佳方法是什么。

示例:

假设有三个进程P1P2P3,下面是该表给出了每个进程的执行时间信息:

-|---------|--------------------|-
 | 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 中的时间范围绘制图形,我可以得到如下所示的内容,并且公共范围以蓝色边框颜色突出显示

Graph representing the process vs time ranges

注意:P1 值为 (0,4) 和 (5,10)

从图中可以看出,输出/结果显然是 [ (3,8) ]

我正在寻找一种解决方案/算法来从给定的输入中推断出这些结果。我很感激能解决以下问题的答案:

解决方法

这可以通过维护前缀和并检查其计数来解决。

但在此之前,您需要进行一些基本的预处理。

对于进程的每次执行,都需要合并重叠的区间。

这是一个很常见的算法,你可以查一下。

所以,在这一步之后,你的输入变成了,

-|---------|--------------------|-
 | 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 举报,一经查实,本站将立刻删除。