Algorithm 求加权重叠区间加权和权重最大的区间的算法

Algorithm 求加权重叠区间加权和权重最大的区间的算法,algorithm,Algorithm,嗯,我想这很难解释,所以我做了一个数字来说明这一点 如图所示,有6个时间间隔。每一个都有它的重量。不透明度越高,权重越高。我想要一个算法来找到权重总和最高的区间。在图中,是间隔5和6的重叠,这是不透明度最高的区域。算法逻辑可以从图中导出。假设时间间隔的分辨率为1分钟,则可以创建一个数组并用于所有计算: 创建24*60个元素的数组,并用0个权重填充; 对于每个时间间隔,将该间隔的权重添加到数组的相应部分; 通过迭代数组找到最大总权重; 再次迭代该数组,并以最大总权重输出数组索引时间。 如果您需要在

嗯,我想这很难解释,所以我做了一个数字来说明这一点


如图所示,有6个时间间隔。每一个都有它的重量。不透明度越高,权重越高。我想要一个算法来找到权重总和最高的区间。在图中,是间隔5和6的重叠,这是不透明度最高的区域。

算法逻辑可以从图中导出。假设时间间隔的分辨率为1分钟,则可以创建一个数组并用于所有计算:

创建24*60个元素的数组,并用0个权重填充; 对于每个时间间隔,将该间隔的权重添加到数组的相应部分; 通过迭代数组找到最大总权重; 再次迭代该数组,并以最大总权重输出数组索引时间。 如果您需要在输出中具有间隔索引,则可以针对稍微不同的任务修改此算法。在这种情况下,数组应该包含作为第二维度的输入时间间隔索引列表,或者它可以是一个单独的数组,具体取决于特定的语言

UPD。我很好奇这个简单的算法是否比@Dukeling建议的更优雅的算法慢很多。我对这两种算法进行了编码,并创建了一个输入生成器来评估它们的性能

发电机:

#!/bin/sh
awk -v n=$1 '
BEGIN {
  tmax = 24 * 60; wmax = 100;
  for (i = 0; i < n; i++) {
    t1 = int(rand() * tmax);
    t2 = int(rand() * tmax);
    w  = int(rand() * wmax);
    if (t2 >= t1) {print t1, t2, w} else {print t2, t1, w}
  }
}' | sort -n > i.txt

简单开启速度慢约20倍。

可以从图中导出算法逻辑。假设时间间隔的分辨率为1分钟,则可以创建一个数组并用于所有计算:

创建24*60个元素的数组,并用0个权重填充; 对于每个时间间隔,将该间隔的权重添加到数组的相应部分; 通过迭代数组找到最大总权重; 再次迭代该数组,并以最大总权重输出数组索引时间。 如果您需要在输出中具有间隔索引,则可以针对稍微不同的任务修改此算法。在这种情况下,数组应该包含作为第二维度的输入时间间隔索引列表,或者它可以是一个单独的数组,具体取决于特定的语言

UPD。我很好奇这个简单的算法是否比@Dukeling建议的更优雅的算法慢很多。我对这两种算法进行了编码,并创建了一个输入生成器来评估它们的性能

发电机:

#!/bin/sh
awk -v n=$1 '
BEGIN {
  tmax = 24 * 60; wmax = 100;
  for (i = 0; i < n; i++) {
    t1 = int(rand() * tmax);
    t2 = int(rand() * tmax);
    w  = int(rand() * wmax);
    if (t2 >= t1) {print t1, t2, w} else {print t2, t1, w}
  }
}' | sort -n > i.txt
简单开启速度慢约20倍

将每个间隔分割为起点和终点

对要点进行排序

从0的和开始

使用以下命令在点之间迭代:

如果你有一个起点:

将总和增加相应间隔的值

如果总和计数高于目前为止的最佳总和,则存储此起点并设置标志

如果你得到了一个终点:

如果设置了标志,则将存储的起点和终点与当前总和一起存储为迄今为止的最佳间隔,并重置标志

按相应间隔的值减少计数

这是从中得出的,它基于未加权版本,即找到重叠间隔的最大数量,而不是最大总权重

例如:

对于此示例:

起点/终点将被排序为:S=起点,E=终点

通过迭代,将标志设置为1S、5S和6S,并将相应的间隔存储在1E、4E和5E,这是在上述起点之后到达的第一个终点

您不会将标志设置为2S、3S或4S,因为总和将低于目前为止的最佳总和

将每个间隔分割为起点和终点

对要点进行排序

从0的和开始

使用以下命令在点之间迭代:

如果你有一个起点:

将总和增加相应间隔的值

如果总和计数高于目前为止的最佳总和,则存储此起点并设置标志

如果你得到了一个终点:

如果设置了标志,则将存储的起点和终点与当前总和一起存储为迄今为止的最佳间隔,并重置标志

按相应间隔的值减少计数

这是从中得出的,它基于未加权版本,即找到重叠间隔的最大数量,而不是最大总权重

例如:

对于此示例:

起点/终点将被排序为:S=起点,E=终点

通过迭代,将标志设置为1S、5S和6S,并将相应的间隔存储在1E、4E和5E,这是在上述起点之后到达的第一个终点


您不会在2S、3S或4S上设置标志,因为总和将低于目前为止的最佳总和。

这是解决此问题的一个非常有趣的算法。我先让问题公开一会儿,看看是否
似乎有更好的答案,但我可能会接受你的答案。谢谢你的回答!这是一个非常有趣的算法来解决这个问题。我会让这个问题公开一会儿,看看是否有更好的答案,但我可能会接受你的答案。谢谢你的回答!
#!/bin/sh
awk '
{t1[++i] = $1; t2[i] = $2; w[i] = $3}
END {
  for (i in t1) {
    p[t1[i] "a" i] = i "S";
    p[t2[i] "b" i] = i "E";
  }
  n = asorti(p, psorted, "@ind_num_asc");
  W = 0.; Wmax = 0.; f = 0;
  for (i = 1; i <= n; i++){
    P = p[psorted[i] ];
    k = int(P);
    if (index(P, "S") > 0) {
      W += w[k];
      if (W > Wmax) {
        f = 1;
        Wmax = W;
        to1 = t1[k]
      }
    }
    else {
      if (f != 0) {
        to2 = t2[k];
        f = 0
      }
      W -= w[k];
    }
  }
  print Wmax, to1 "-" to2
}
' i.txt > a2.txt
$ ./gen.sh 1000
$ time ./a1.sh
real    0m0.283s
$ time ./a2.sh
real    0m0.019s
$ cat a1.txt
24618
757
$ cat a2.txt
24618 757-757
$ ./gen.sh 10000
$ time ./a1.sh
real    0m3.026s
$ time ./a2.sh
real    0m0.144s
$ cat a1.txt
252452
746
$ cat a2.txt
252452 746-746
$ ./gen.sh 100000
$ time ./a1.sh
real    0m34.127s
$ time ./a2.sh
real    0m1.999s
$ cat a1.txt
2484719
714
$ cat a2.txt
2484719 714-714
1S, 1E, 2S, 3S, 2E, 3E, 4S, 5S, 4E, 6S, 5E, 6E