我想根据两个条件对项目列表进行排序。每个项目都包含一个间隔和一个数字。
Items[0] = {Interval=[10..30], Number = 7}
Items[1] = {Interval=[20..40], Number = 5}
Items[2] = {Interval=[30..50], Number = 3}
Items[3] = {Interval=[40..60], Number = 2}
我想根据时间间隔对列表进行“模糊排序”:一个顺序,其中前一个项目的时间间隔下限不大于后一个项目的时间间隔上限。
例如,items[3]
不应在items[0]
之前排序,因为[40..60]
严格大于[10..30]
。但是items[1]
可能在items[0]
之前或之后发生,因为它们的间隔重叠。
因此,可以通过按每个区间内的下限或上限,中点或任意数字排序来实现有效的排序。
从所有这些可能的排序中,我想选择一个按Number
排序的排序作为第二个条件。对于所有可以交换的项目,因为它们的间隔重叠,所以我想交换它们,以使Item.Number递增。
因此,以下将是有效的顺序,按Interval
升序排序,然后按Number
升序排序:
Items[2] = {Interval=[30..50], Number = 3}
Items[1] = {Interval=[20..40], Number = 5}
Items[0] = {Interval=[10..30], Number = 7}
Items[3] = {Interval=[40..60], Number = 2}
有多个同等有效的解决方案。使用相同的条件,这也将是有效的订单:
Items[0] = {Interval=[10..30], Number = 7}
Items[3] = {Interval=[40..60], Number = 2}
Items[2] = {Interval=[30..50], Number = 3}
Items[1] = {Interval=[20..40], Number = 5}
除了蛮力外,是否有一种有效的算法来找到这种排序?
此类型或排序的名称吗?
答案 0 :(得分:1)
制作一个图形,其中每个顶点都是一个间隔。
对于每对顶点:如果它们不重叠,则从早到晚的间隔之间添加有向边。
通过遍历所有线对可以避免O(n²)运行时间。如果我们按结束时间对时间间隔进行排序,则按此顺序进行迭代将使我们能够快速找到与我们遇到的任何给定时间间隔重叠的所有时间间隔(我们可以在此时间间隔开始之前的列表中查找最新的结束时间)时间)。然后,我们需要弄清楚如何避免创建任何不必要的边缘-对于[1,2],[3,4]和[5,6],在[1,2]和[5]之间会有不必要的边缘,6],因为它们是通过[3,4]连接的。
边缘代表在排序列表中哪个间隔之前需要间隔。
直到没有顶点,选择一个没有输入边的顶点。将其作为排序列表中的下一个元素,并删除该顶点的所有出线边。
对于上述情况,如果将没有传入边的所有顶点放入按Number
排序的集合中,则可以在每个点处选取最小值以强制执行次级排序标准。
这将是O(n²),但也许可以优化为O(n log n)。
以您的示例为例:
Items[0] = {Interval=[10..30], Number = 7}
Items[1] = {Interval=[20..40], Number = 5}
Items[2] = {Interval=[30..50], Number = 3}
Items[3] = {Interval=[40..60], Number = 2}
图形中的唯一边是[10,30]→[40,60]。
这意味着我们可以选择[40,60]以外的任何顶点。
我们首先选择[30,50],因为它在其余元素之间的数字最少(3 <5和3 <7)。
然后我们从5 <7开始选择[20,40]。
然后我们选择[10,30]并将边线移到[40,60],这将允许我们选择[40,60]。
最后我们选择[40,60]。