Javascript 物体间最短距离

Javascript 物体间最短距离,javascript,algorithm,Javascript,Algorithm,假设我有这样一个对象: let objs = { obj1: [ 0, 10 ], obj2: [ 3, 9 ], obj3: [ 5, 12, 14 ] } 每个obj有多个距离点,但只应选择一个与其他obj的距离点组合 我可以根据上面的距离点以12种方式组合三个对象 例如,它可以变成[0,3,5]; 在这种情况下,三个对象之间的总距离为5-0,即5 或者它可以变成[10,9,5],距离是10-5=5 组合也可以是[0,3,12],距离为12-0=12 我想要达到的是找到最短的组合,在这种情

假设我有这样一个对象:

let objs = { obj1: [ 0, 10 ], obj2: [ 3, 9 ], obj3: [ 5, 12, 14 ] }
每个obj有多个距离点,但只应选择一个与其他obj的距离点组合

我可以根据上面的距离点以12种方式组合三个对象

例如,它可以变成[0,3,5]; 在这种情况下,三个对象之间的总距离为5-0,即5

或者它可以变成[10,9,5],距离是10-5=5

组合也可以是[0,3,12],距离为12-0=12

我想要达到的是找到最短的组合,在这种情况下应该是[10,9,12];距离为12-9=3

所以我想到了一个接一个地表演组合;我可以使用嵌套循环来实现这一点,但这将是非常低效的。
我可以使用什么最有效的方法来实现这一点?

您可以获得笛卡尔积,然后通过使用最大值和最小值的较小增量来减少数组

let objects={obj1:[0,10],obj2:[3,9],obj3:[5,12,14]},
数据=对象。值(对象),
笛卡尔=数据.reduce((a,b)=>a.reduce((r,v)=>r.concat(b.map(w=>[].concat(v,w)),[]),
结果=cartesian.reduce((a,b)=>Math.max(…a)-Math.min(…a)a.join(“”))

。作为控制台包装{max height:100%!important;top:0;}
我认为没有什么比嵌套/递归循环更好的了,在最坏的情况下,您仍然需要检查所有的组合。但是,我认为应用将提供一个很好的优化,因为它将尽早修剪距离不太好的分支-还利用了每个对象的点都已排序的事实,因此您可以一次修剪多个选择

实际上,对于每个对象,我们可以删减到目前为止所选间隔最下方和最上方的两个选项。因此,我估计最坏情况下的复杂度为
O(k*(2+log k)n)
(给定
n
对象的平均
k
已排序点),而不是原始枚举的
O(kn)


诚然,这比尼娜的第二种方法的
O(kn log(kn)+kn²)
或马拉斯算法的
O(kn log(kn))
更糟糕,后者可以通过在已经排序的列表上使用一个变量来进一步改进为
O(kn log n)

对于obj中的每个值v,创建一对(v,O),然后按对的第一个元素对所有对进行排序。需要O(n日志n)

现在,您需要从排序序列中选择一些连续的元素,每个o中至少有一个在其中。您可以在O(n log n)中选择最佳答案(或使用哈希映射选择O(n))

首先选择满足条件的序列的最小前缀。做两个指针,一个是连续选择元素的开始,另一个是结束

开始=1,结束=x(其中x是每个对象在所选集合内的最小值)

然后尝试增加开始(通过删除所选子序列的第一个元素)和增加结束(只要有必要)。 取结束值和开始值之间的最小差值,这就是您的答案

正如我所说的,为了跟踪所有对象是否都在其中,请创建一个映射/哈希映射,您可以在其中为每个对象存储所选序列中的对象量。 增加“开始”时,必须减少子序列中某些对象的数量。然后,您应该增加end,直到每个对象在所选子序列中出现的次数为非零。(要获得O(n log n)复杂度,请存储值为0的对象数。增加任何对象时,请减小计数器;将任何对象的数量减少到0时,请增大计数器)


结果总是正确的,没有使用试探法。

两件小事:“最短”在这里也不清楚(最短运行时?/最短代码?/…)-您知道存在O(n)方法吗?如果没有,可能没有,这将是一个无法实现的限制。@schnaader,我已经就你的问题修改了我的帖子。如果您有问题,请告诉我:)它总是只有三个对象吗?您的对象平均有多少个点?哪个数字可以变大?@Bergi,对,因此对象的数量没有限制,每个对象中的点数也可以是任意的。但是让我们假设这些数字到现在为止是固定的。解决方案是不是:“每个框选择最大的一个,然后遍历其余的框,找到最小的一个,比最初选择的要大;如果没有更大的,则忽略”,这样-算法就可以:1。10、9、退出;2.9,10,12-发现,3。14,10,退出。可能需要从两个方面考虑(即,选择最低的一个,然后通过其余部分找到最大的一个)构造笛卡尔积正是OP所说的“嵌套循环”的意思。我认为您的第二种方法使用了@Maras的答案中详述的思想-您应该投票表决!这基本上是我想用我的A*算法建议来实现的,但A*不合适,因为它的启发式在这里是无用的(我们无法估计进一步的成本)。@是的,我想我错了-自从Maras发布了他们的答案后,我就有这种感觉。尽管如此,我还是不会删除我的答案,因为我认为分支和绑定有其优点。你甚至不需要对象的(散列)映射-你只需要给它们索引并将计数存储在数组中。有时候并不那么简单,但总的来说是的,只要你可以轻松地枚举对象,你就可以使用数组