以log(n)的时间求矩形内的点
来源:互联网 发布:grub2手动引导ubuntu 编辑:程序博客网 时间:2024/05/01 15:55
版权所有,如需转载,请注明出处(http://blog.csdn.net/dengdefang/article/details/13771467)
设想这么一个简单的问题,在一个平面上有n个点,给定一个矩形,问位于矩形内的点有哪些。
这个问题的简单思路非常简单,每次遍历所有点,看其是否在给定的矩形中。时间复杂度呢?单次查询的时间就是一次遍历的时间,也就是O(n),但如果给定的点基本不变,但查询量特别大,每次查询都要以O(n)的复杂度。能不能把给定的数据预处理一下,然后以后每次查询的复杂度降低呢?
一个基本的思路是把相邻的点用最小包围矩形包起来,然后再递归地处理这些矩形,以更大的最小包围矩形包围这些相邻的矩形。下面是个简单的例子:
在查询一个矩形内的所有点时,先把矩形和树的根求交,如果没有交集,说明矩形内没有点。否则说明矩形内可能包含有给定的点,于是就把矩形与根的儿子求交,这样递归下去即可。通过这种方法,我们在建树的时候,用了O(n)的时间,再以后每次查询的时候,大概是log(n)的时间
现在的难题是:如果判断两个点是否相邻?用他们之间的距离来作为标准肯定不合适
希尔伯特距离和希尔伯特树(http://en.wikipedia.org/wiki/Hilbert_R-tree)在这里可以得到很好的应用。什么是希尔伯特距离?
我们把一个给定区域按如下方式来划分,划分完成后,每个点到原点处的线段长度就是希尔伯特距离。如在H2中,点2的希尔伯特距离是2,点6的希尔伯特距离是6.
现在我们把给定的所有点的希尔伯特距离都算出来,然后根据希尔伯特距离来将它们作升序排序,然后就可以建树了
如何算希尔伯特距离呢?暴力方法肯定不行,有个比较好的方法如下:
- For all points, find max_x and max_y.
- Find the max of max_x and max_y and call this max_xy.
- If max_xy is a power of two, leave it. Else make it the next higher power of two.
- For each point:
1. Initialize w to be max_xy / 2. Dist = 0.
2. Find the quadrant on a hilbert curve that the point isin.
3. Dist += (quadrant * w * w)
4. w becomes w / 2
5. Calculate xnew and ynew according to the formulas
6. Repeat steps 2 to 5 until w becomes 0
Quadrant
x_new
y_new
0
y
x
1
x
y - w
2
x - w
y - w
3
w - y - 1
w * 2 - x - 1
/** * Find the Hilbert order (=vertex index) for the given grid cell * coordinates. * @param x cell column (from 0) * @param y cell row (from 0) * @param r resolution of Hilbert curve (grid will have Math.pow(2,r) * rows and cols) * @return Hilbert order */public static int encode(int x, int y, int r) { int mask = (1 << r) - 1; int hodd = 0; int heven = x ^ y; int notx = ~x & mask; int noty = ~y & mask; int temp = notx ^ y; int v0 = 0, v1 = 0; for (int k = 1; k < r; k++) { v1 = ((v1 & heven) | ((v0 ^ noty) & temp)) >> 1; v0 = ((v0 & (v1 ^ notx)) | (~v0 & (v1 ^ noty))) >> 1; } hodd = (~v0 & (v1 ^ x)) | (v0 & (v1 ^ noty)); return interleaveBits(hodd, heven);}/** * Interleave the bits from two input integer values * @param odd integer holding bit values for odd bit positions * @param even integer holding bit values for even bit positions * @return the integer that results from interleaving the input bits * * @todo: I'm sure there's a more elegant way of doing this ! */private static int interleaveBits(int odd, int even) { int val = 0; // Replaced this line with the improved code provided by Tuska // int n = Math.max(Integer.highestOneBit(odd), Integer.highestOneBit(even)); int max = Math.max(odd, even); int n = 0; while (max > 0) { n++; max >>= 1; } for (int i = 0; i < n; i++) { int bitMask = 1 << i; int a = (even & bitMask) > 0 ? (1 << (2*i)) : 0; int b = (odd & bitMask) > 0 ? (1 << (2*i+1)) : 0; val += a + b; } return val;}
之后的建树和搜索就不用多介绍了
- 以log(n)的时间求矩形内的点
- 求n*m网格内矩形的数目
- 求n^m 时间复杂度log(m)的算法
- 【51nod】1291 Farmer 【求n*m的矩形内全1的i*j的矩形个数】【dp】
- R求一个时间前N天的时间点
- opencv:求区域的内接矩形
- 求包括n个矩形的最小矩形面积模板
- 求点序列的包围矩形
- O(logN)时间复杂度内求整数的N次方以及矩阵的N次方
- 谷歌2014年中国区校园招聘B轮题目二(求N个矩形内的所有点到其中一点的街区距离之和最短)解法探讨与代码实现(C++)
- 已知矩形的任意三个点,求第四个点
- 线性时间O(n)内求数组中第k大小的数
- 算法题目---求公司内员工的年龄排序---用空间换取时间O(n)
- 求N内的所有素数
- 求1-N内的素数
- 求N内的所有素数
- 求N内的所有素数
- 算法-求n内的所有质数
- UITableView分割线样式与颜色
- 【记录】cygwin下折腾个人配置环境
- 用C语言获取任意文件的长度(可能大于2GB)
- Flex中的Bindable的用法
- 为IEnumerable接口添加增删查等操作
- 以log(n)的时间求矩形内的点
- 关于HASH和MD5
- lazarus连接access数据库
- 九步确定你的人生目标和制定达到目标的计划
- iptables 防火墙
- 2.Dynamic Programming on Stolen Values【dp】
- snprintf拷贝字符串
- Iphone 手机助手 Plist 文件详解 (二)
- javascript 实现动画