我有角度间隔(弧度)[0,2π]
我必须找到大多数间隔中的角度。 在C ++中找到它的最佳方法是什么? 如何表示角度间隔?
答案 0 :(得分:4)
您可以实现一个简单的sweep-line algorithm来解决此问题。
对于每个间隔,将间隔的开始和结束添加到矢量;对此向量进行排序,然后迭代它。如果你有任何穿过2π边界的区间,只需将其分成两个区间,这两个区间都在(0,2π)内。
当你遍历列表时,记录当前点有多少重叠的itervals,以及你到目前为止看到的最佳角度(以及在该角度重叠的间隔数)。一旦到达终点,就会知道最佳角度是什么。
如果你需要多个角度,你可以很容易地采用这种方法来记住最大重叠的间隔,而不是单个角度。
答案 1 :(得分:1)
我的解决方案将涉及一个间隔开始对的列表以及多少个间隔重叠它:
1 2 3 2 1
|---------|--------|-----|---------------|------|
|------------------|
|--------------|
|---------------------|
|----------------------------|
因此,对所有起点和终点进行排序并遍历列表,为每个新区间分配与其重叠的区间数(如果它是起点,则增加它,否则减少)。然后从重叠计数中取最大值。
答案 2 :(得分:1)
我是通过将[0,2π]的分区保持在与间隔覆盖相对应的范围内来实现的,并且每个范围都有一个计数。首先,这里的算法如何在没有任何区间跨越0(或2π)的条件下工作。还假设间隔按如下方式归一化:如果间隔结束于0,则改变为以2π结束;如果它从2π开始,则改为从0开始。
处理间隔i
:
s
的第一个(范围,计数)对(称之为i.start >= s.range.start
)(即范围包含i.start
)。 (请注意,如果i.start
是一个范围的结尾,那么它将是另一个范围的开头;这将选择它作为开始的对。)e
的最后一个(范围,计数)对i.end <= e.range.end
。 (注意,如果i.end
是一个范围的开头,那么它将是另一个范围的结尾;这将选择它结束的对。)i.start > s.range.start
(i.range
在s
内部开始),请将s
分成两个(范围,计数)对s1 = ([s.range.start, i.start], s.count)
和{{1} }}。使用s2 = ([i.start, s.range.end], s.count)
和s
(按此顺序)替换列表中的s1
。s2
,请以与上一步骤平行的方式替换i.end < e.range.end
,使用e
进行拆分。i.end
(或s
如果s2
在步骤3中拆分)的每一对,直至并包括s
(或e
if {{在步骤4)中拆分1}},在计数中加1。如果你不关心跟踪包含特定角度的实际间隔数,只是它是最大值,那么跨越0(或2π)的间隔的簿记会更容易:只需要补充interval(反转开始和结束)并从步骤5中的计数中减去1而不是添加。如果确实需要绝对计数,则执行补码技巧,然后在列表中的每个计数中加1。
上述将不能正确处理邻接的间隔(例如:[0,π/ 3]和[π/ 3,π];或[2π/3,2π]和[0,1])。在这些情况下,据我所知,它们相邻的角度(π/ 3或0)应计为两个间隔。可以调整上述算法,以便当间隔开始与范围结束点重合时,在所讨论的对之后插入新的(范围,计数)对;新对将具有单角度范围(即e1
)。类似的过程适用于在间隔结束时开始的范围。我认为通过这些调整,上述算法可以正确处理所有情况。
答案 3 :(得分:0)
如果你不象征性地这样做,我认为你会遇到奇怪的边缘情况。
您的角度范围不仅不能完全表示为二进制分数(引入舍入误差),而且它们是不合理的。 (Pi
大于3.14159265359但小于3.14159265360;除了符号之外,你怎么说角度等于Pi
/ 2?)
我认为最有效的方法是依次采用所有间隔组合,确定它们的交集,并查看哪些组合间隔是大多数单独间隔交叉的结果。
这也有一个额外的好处,不仅仅是一个,而是所有满足你条件的角度。