假设坐标(x1,y1)中的一个点支配另一个点(x2,y2),如果x1≤x2且y1≤y2;
我有一组点(x1,y1),....(xn,yn),我想找到支配对的总数。我可以通过将所有点相互比较来使用强力来做到这一点,但这需要时间O(n 2 )。相反,我想用分而治之的方法在时间O(n log n)中解决这个问题。
现在,我有以下算法:
绘制一条垂直线,将点集点分为两个相等的子集P left 和P right 。作为基本情况,如果只剩下两点,我可以直接比较它们。
递归计算P left 和P right
一些征服步骤?
问题在于我无法看到“征服”步骤应该在这里。我想计算有多少支配对从P left 到P right ,但我不知道怎么做而不比较两者中的所有点部分,需要时间O(n 2 )。
任何人都可以给我一个关于如何做征服步骤的提示吗?
所以y坐标的两半是:{1,3,4,5,5}和{5,8,9,10,12}
我画了分界线。答案 0 :(得分:6)
假设您按两个y坐标按升序分别对两半中的点进行排序。现在,看看两半中最低的y值。如果左边的最低点的y值低于右边的最低点,则该点由右边的所有点控制。否则,右边的底部点不会占据左边的任何东西。
在任何一种情况下,您都可以从两半中的一半中删除一个点,并使用剩余的排序列表重复该过程。这样O(1)每点工作,所以如果总共有n个点,那么O(n)工作(排序后)就可以计算两半中支配对的数量。如果你以前见过它,这类似于计算数组中反转的算法。
考虑到对点进行排序所需的时间(O(n log n)),这个征服步骤需要O(n log n)时间,给出重现
T(n)= 2T(n / 2)+ O(n log n)
根据Master Theorem解决了O(n log 2 n)。
但是,你可以加快速度。假设在你开始划分amd征服步骤之前,你用y坐标预先分配点,做一次O(n log n)工作。使用与最接近的点对问题类似的技巧,然后可以在每个大小为n的子问题(参见the discussion at this bottom of this page)中以O(n)时间对每一半中的点进行排序以获取详细信息。这会将重复发生变为
T(n)= 2T(n / 2)+ O(n)
根据需要解决O(n log n)。
希望这有帮助!
答案 1 :(得分:1)
通过这种方式,你只需要O(n ^ 2)来划分子集...
我的方法会有所不同
您还可以通过单独的X和Y测试进一步加快速度,然后结合结果,这将导致O(n + 3.n.log(n))
希望它有所帮助,...当然,如果你坚持使用细分方法,那么我没有更好的解决方案。
PS。对于这个你不需要任何额外的递归只需3x排序和任何点只有一个uint因此内存要求不是那么大,甚至应该比递归调用细分递归更快
答案 2 :(得分:0)
此算法在 O(N * log(N))中运行,其中N是点列表的大小,它使用 O(1)额外空格。
执行以下步骤:
这是有效的,因为您确定如果所有具有更大y坐标的对具有比当前点更小的x坐标,则您找到了支配点。排序步骤使其真正高效。
这是Python代码:
def my_cmp(p1, p2):
delta_y = p1[1] - p2[1]
if delta_y != 0:
return delta_y
return p1[0] - p2[0]
def count_dom_points(points):
points.sort(cmp = my_cmp)
maxi = float('-inf')
count = 0
for x, y in reversed(points):
if x >= maxi:
count += 1
maxi = x
return count