昨天被问到一道题目,感觉挺有意思,这里记录一下:
题目:给定一个m*m的矩形区域,已知一点的(x,y)坐标,如何找到离周围xkm的所有店家?
这里需要用到一个叫做GeoHash的算法。
这个算法是什么作用呢?
GeoHash可以将地图网格化,然后把一个位置的坐标转换成一个可以排序的,可以比较的字符串编码,说到底就是将一个二维的数据映射成一个一维的数据。
核心代码:
public static String GeohashEncode(double latitude,double longitude,int precision=12){
boolean even=true;
int bit=0;
int ch=0;
String geohash="";
double[] lat={-90.0,90.0};
double[] lon={-180.0,180.0};
if(precision<1||precision>20) precision=12;
while(geohash.length()<precision){
double mid;
if(even){
mid=(lon[0]+lon[1])/2;
if(longitude>mid){
ch|=Bits[bit];
lon[0]=mid;
}
else{
lon[1]=mid;
}
}
else{
mid=(lon[0]+lon[1])/2;
if(latitude>mid){
ch|=Bits[bit];
lat[0]=mid;
}
else{
lat[1]=mid;
}
}
even=!even;
if(bit<4) bit++;
else{
geohash+=Base32[ch];
bit=0;
ch=0;
}
}
return geohash;
}
base32编码表如下:
0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | |
base32 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | b | c | d | e | f | g |
十进制 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 |
base32 | h | j | k | m | n | p | q | r | s | t | u | v | w | x | y | z |
下面回到这个题目,题目要求我们找到所有距离坐标Xkm的商店,我们可以采取以下的方法:
以给定的点向外拓xkm,分别对周围8个坐标进行GeoHash(如下图),然后提取字符串的公共部分,最后查找周围点的GeoHash值以xx开头的就是满足题意的商家。