Algorithm 支持对一组二维点进行特定查询的数据结构
我有一组2D点,我希望能够使用参数Algorithm 支持对一组二维点进行特定查询的数据结构,algorithm,Algorithm,我有一组2D点,我希望能够使用参数x_min和n进行以下查询:具有最大y的n点有哪些x_min 要在Ruby中重新措辞: class PointsThing def initialize(points) @points = points end def query(x_min, n) @points.select { |point| point.x > x_min }.sort_by { |point| point.y }.take(n) end end
x_min
和n
进行以下查询:具有最大y
的n
点有哪些x_min
要在Ruby中重新措辞:
class PointsThing
def initialize(points)
@points = points
end
def query(x_min, n)
@points.select { |point| point.x > x_min }.sort_by { |point| point.y }.take(n)
end
end
理想情况下,我的类还支持插入和删除操作
我想不出一种数据结构能让查询在不到O(|@点|)的时间内运行。有人知道吗?如果您的数据没有排序,那么您别无选择,只能检查每个点,因为您无法知道是否存在另一个点,其中y大于所有其他点的y,并且对于该点,
x>x\u min
。简言之:如果你不全部检查,你就不知道是否应该包括另一点
在这种情况下,我假设不可能按照您的要求签入sub线性时间,因为您必须全部检查它们。搜索所有对象的最佳情况是线性
如果对数据进行了排序,那么最好的情况是恒定时间(所有n个点都是y最大的点),最坏的情况是线性的(所有n个点都是y最小的点)。平均情况会更接近常数,我想如果你的x和x_min在特定范围内都是随机的
如果您想将其缩放(也就是说,可以有较大的n值),那么您还需要对结果集进行排序,因为您需要对照它检查新的潜在点,并在插入时删除最小值(如果大小>n)。使用树,这可以是日志时间
所以,要做整个事情,最坏的情况是对于未排序的点,在这种情况下,您看到的是nlog(n)时间。排序点更好,在这种情况下,您可以查看log(n)时间的平均情况(再次假设x和x_min的值大致随机分布),这是次线性的
如果一开始不清楚为什么排序的点会有固定的搜索时间,我将在这里快速地讨论 如果y值最大的n个点都有
x>x_min
(最佳情况),那么您只需要从顶部抓取您需要的,因此这种情况很明显
对于平均情况,假设x和x_min大致随机分布,x>x_min
的几率基本上是一半。对于任意两个随机数a和b,a>b
与b>a
一样可能为真。这与x和x_min是一样的x>x_-min
与x_-min>x
的概率相同,即概率为0.5。这意味着,对于您的分数,平均每检查一秒,您的x>x_min
要求将得到满足,因此您将平均检查2n个点,以找到满足您标准的n个最高点。所以最好的情况是c时间,平均值是2c,这仍然是常数
但是,请注意,对于接近集合大小的n值,这隐藏了这样一个事实,即您正在遍历整个集合,基本上将其恢复到线性时间。所以,如果你假设n的随机值在你的集合的大小范围内,那么我关于时间常数的断言就不成立了
如果这不是一个纯粹的学术问题,而是出于某种实际需要,那就要视情况而定
(编辑)
我刚刚意识到,我的常量时间断言假设了一种数据结构,在这种结构中,您可以直接访问最高值,并可以按顺序访问较低的值。如果提供给您的数据结构不符合该描述,那么显然情况并非如此。在这种情况下,一些预计算将有所帮助 首先以x_min为轴心元素对点集进行分区 然后,对于位于x_min右侧的一组点,基于y坐标构建max_堆 现在以以下方式运行查询:在构建的最大值堆上执行n个extract\u max操作 查询的运行时间为logx+log(X-1)+。。。。。日志(X-(n-1)) 日志X:用于第一次提取最大值操作 日志X-1:用于第二次提取最大值操作,依此类推 X:原始最大堆的大小
即使在最坏的情况下,当您的n符号 设
p
为点集
让top_y(n,x_min)
描述从p
收集n
点的查询,其中x坐标大于或等于'x_min'的点的最大y坐标
设x_0
为点集中x坐标的最小值。通过点集P
的x坐标集,将x_0
右侧的x轴划分为一组左侧闭合、右侧打开的间隔I_I
,使得min(I_I)
是P
第四个但最小的x坐标。将x
的坐标秩r(x)
定义为区间的索引x
是元素,如果x
,则定义为0
请注意,r(x)
可以在O(log#({I_I}))
中使用二叉搜索树进行计算
简单解决方案
O(#p log#p)
和空间O(#p)
中保存此数组A\u i:A\u i.x
,计算所有其他项,直到计数器达到n
或您位于A
的末尾,来处理每个查询top\y(n,x\u min)
。此处理需要O(n)
时间和O(1)
空间top_y(n_0,a_0);a_0