【问题标题】:Finding the shortest segment a point belongs to找到一个点所属的最短线段
【发布时间】:2014-05-22 20:22:51
【问题描述】:

我有一个List<> 的一维段,每个段由一个包含开始和结束的struct 表示(x1x2)。段可以重叠。该列表按开始排序 (x1)。

如何有效地找到包含特定点 x 的最短线段?

目前,我使用list.BinarySearch 查找x >= x1 的第一个段,这是有效的。然后我继续遍历列表,一次一个片段,直到x x1,找到x1 x x2 的最短片段,这不是那么有效。

如何改进该算法以获得更好的速度?我觉得可以,但我卡住了。

此问题与Shortest distance between a point and a line segment 不重复。

【问题讨论】:

  • 对于你给出的数据结构,你的算法很好。可能的改进取决于多种因素,例如:您更改数据结构的意愿如何,平均有多少段共享相同的起点等。
  • @mbeckish,我愿意以任何方式更改数据结构,例如我可以把它变成一棵树。共享相同的起点和重叠是不可能的,但可能。感谢您的想法。
  • 是否必须动态支持插入和删除区间?
  • 另外,您的查询和端点是整数吗?
  • @NiklasB.,它不必动态支持插入/删除。每次输入数据更改时,它都会整体重建。端点确实是整数。

标签: c# algorithm optimization


【解决方案1】:

看看区间树 (http://en.wikipedia.org/wiki/Interval_tree) 和段树 (http://en.wikipedia.org/wiki/Segment_tree)。

这些支持高效查询以报告跨越给定点的所有区间。

我不知道有效报告最小间隔的解决方案。

【讨论】:

  • 只需使用二叉搜索树扩充(最小间隔)并获得表示与给定点相交的间隔的子树
【解决方案2】:

如果您允许自己 O(n log n) 的预处理时间,您可以构建一个数据结构,在 O(log n) 时间内为您提供任何查询点的答案。对区间的所有端点进行排序(跟踪它们对应的区间),并从左到右处理端点。还要维护一个按间隔长度排序的间隔的自平衡二叉搜索树。每次遇到左端点时,将区间添加到树中,每次遇到右端点时,从树中删除区间。此外,对于您遇到的每个端点,记录包含端点和前一个端点之间的子间隔的最短间隔(树中最左边的节点)。 (如果没有间隔,记录“无”)所以最后你将有一个 2n - 1 个子间隔的数组,它知道是否有一个覆盖子间隔的间隔,如果有,最短的间隔是多少.然后给定一个点,你可以对结构进行二分搜索,找到包含该点的子区间,并报告是否存在包含该点的区间,如果有,最短区间是多少。

【讨论】:

  • 是的,正是我要建议的。如果标准库中没有支持删除的堆,可以使用二叉搜索树来代替
  • 好点,我将其切换为自平衡二叉搜索树。
猜你喜欢
  • 2010-10-25
  • 2015-01-25
  • 2023-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多