美團面試官問我如何查詢附近商家,我這樣說可以懟翻他!

2020-12-05 程式設計師明明

就比如我們日常電腦美團或者餓了麼點外賣,附近的商家幾乎都是秒回的,最簡單的理解,我們可以用經緯度來計算。

經緯度

談到經緯度。想必大家在中學時代的地理課本裡早就學過了。我們把地球分成縱橫交錯的一些格子,每個點都可以用橫豎坐標來表示。橫線表示緯度,範圍在[-90°, +90°],豎線表示經度,範圍在[-180°, +180°]。

我們當前的經緯度,可以從wifi或者手機的GPS獲取。

計算距離

接下來我們計算兩點的距離。

地球是一個近乎標準的橢球體,它的赤道半徑為6378.140千米,極半徑為6356.755千米,平均半徑6371.004千米。如果我們假設地球是一個完美的球體,那麼它的半徑就是地球的平均半徑,記為R。如果以0度經線為基準,那麼根據地球表面任意兩點的經緯度就可以計算出這兩點間的地表距離(這裡忽略地球表面地形對計算帶來的誤差,僅僅是理論上的估算值)。

設第一點A的經緯度為(LonA, LatA),第二點B的經緯度為(LonB, LatB),按照0度經線的基準,東經取經度的正值(Longitude),西經取經度負值(-Longitude),北緯取90-緯度值(90-Latitude),南緯取90+緯度值(90+Latitude),則經過上述處理過後的兩點被計為(MLonA, MLatA)和(MLonB, MLatB)。那麼根據三角推導,可以得到計算兩點距離的如下公式:

C = sin(MLatA)*sin(MLatB)*cos(MLonA-MLonB) + cos(MLatA)*cos(MLatB)Distance = R*Arccos(C)*Pi/180

google maps的腳本裡代碼

private const double EARTH_RADIUS = 6378.137;

private static double rad(double d)

{

return d * Math.PI / 180.0;

}

public static double GetDistance(double lat1, double lng1, double lat2, double lng2)

{

double radLat1 = rad(lat1);

double radLat2 = rad(lat2);

double a = radLat1 - radLat2;

double b = rad(lng1) - rad(lng2);

double s = 2 * Math.Asin(Math.Sqrt(Math.Pow(Math.Sin(a/2),2) +

Math.Cos(radLat1)*Math.Cos(radLat2)*Math.Pow(Math.Sin(b/2),2)));

s = s * EARTH_RADIUS;

s = Math.Round(s * 10000) / 10000;

return s;

}

如果我們相距的兩點不是特別遠(相對地球半徑而言),我們就可以把他們近似看成平面上的兩點,可以用下面的公式計算距離:

當我們的商戶不是太多的時候,就可以遍歷所有商戶,依次計算出所有的商戶同我的距離d1 d2 ... dk,然後按照距離從小到大排序,得到我們想要的結果。

我們來算算時間複雜度。

1.遍歷所有的點,計算距離,是一個O(n)複雜度的算法;

2.排序做TopN,按照快排來算的話,基本上是一個O(nlogn)的複雜度;

所以總的複雜度趨近於O(nlogn)。

那麼當有大量商戶的時候該怎麼辦呢?

方案一:簡單的分布式計算:

將商鋪信息進行分組,分別進行排序取出前N的推薦,最後把前面排序的結果,再進行一次TopN排序,這樣就可以找到最近的商鋪信息了。

這種實現方式簡單,但是有幾個比較嚴重的問題:

隨著商戶的增長,進行的分組會越來越多,呈直線上升趨勢;有時結果不會特別精確。假設全部的最優解都在某一個分組裡,可能不會進到最後的歸併排序裡。

剛剛我們已經提到過了,我們用經線和緯線來分割地球,此時的地球已經被我們分成一塊一塊的了,我們看看下面這個圖:

如同我們的紅箭頭指的那個點,要找到它附近的點,是不是直接取出它所在的經緯度格子的所有點就可以了呢?再加上圍繞它所在格子的八個格子的所有點,那就一定是這個點周圍的所有點了!

那麼接下來就是如何給這些經緯度格子編碼的問題了!

編碼

我們用經度切割,以上海經緯度121.43333,34.50000來舉例:

以0°為中軸,將地球切成兩半[-180°,0°),[0°,180°],並對他們進行二進位編碼,左邊為0,右邊為1;

此時上海的經度編碼就是1。

我們再切割一次,將精度切成[-180°,-90°),[-90°,0°),[0°,90°),[90°,180°],按照二進位編碼,分別為:00,01,10,11

此時上海的經度編碼就是11

如此這樣重複N次,我們就可以將地球按經度切割成很多很多的小格子,如果切割的次數足夠多,每一個格子相當於一個點,那也會得到對應這個小塊兒的二進位編碼。比如上海的的經度121.43333經過多次切割得到如下這個表格:

比如此時我們分割了8次,上海的經度編碼就是11010110。隨著切分的繼續,我們可以得到更長的編碼,這樣就可以對應更細緻的區間。

按照同樣的方法,我們切割一下緯度,則上海的緯度34.50000可以得到如下表格編碼:

上海的緯度編碼就是:10110001

最終我們得到的上海經緯度編碼為

(121.43333,34.50000)-->(11010110,10110001)

統一編碼

為了方便記錄,我們把經度和維度的二進位格子編碼進行合併,按經度、緯度、經度、維度……這樣的順序,一位一位的進行放置:

(11010110,10110001)-->1110011100101001

奇數位的紅色是經度編碼,偶數位的黑色是緯度編碼

我們可以用16進位、32進位、64進位這樣的進位來縮短編碼長度。這裡業界推薦的是32進位

所以1110011100101001的32編碼為:wwn(取三位有效)

精度

有了這樣的編碼,那到底要劃分多少次,我們的數據才足夠精確呢?維基百科上找到了這樣的一張對應表:

當有一個32位數字的時候,精細度大概是2500公裡,當有8個數字的時候,精細度大概是0.019km = 19米。也就是說,8個32位的數字 對應 8*5=40個二進位數,也就是經緯度分別劃20次,就可以達到19米的精細度。

這個就是著名的 Geohash

值得注意的是:

1.Geohash比直接用經緯度的高效很多,而且使用者可以發布地址編碼,既能表明自己位於某地方附近,又不至於暴露自己的精確坐標,有助於隱私保護。

2.GeoHash用一個字符串表示經度和緯度兩個坐標。在資料庫中可以實現在一列上應用索引(某些情況下無法在兩列上同時應用索引)

3.GeoHash表示的並不是一個點,而是一個矩形區域

4.GeoHash編碼的前綴可以表示更大的區域。例如wx4g0ec1,它的前綴wx4g0e表示包含編碼wx4g0ec1在內的更大範圍。這個特性可以用於附近地點搜索

查找

通過上面的方法,我們就可以將所有商鋪的經緯度給一個編碼存進資料庫,建立索引。這樣根據當前自己的經緯度計算相應的編碼,查詢資料庫

select * from merchant where code = 'xxx'

這樣就可以獲取附近的商鋪了,是不是超級開心!

當然不要忘記,如果兩個點距離很近,但是劃到了兩個格子裡,這樣是找不到的,所以我們還要把附近的8個格子的編碼分別算出來一起查詢,最後進行匯總!

相關焦點

  • 面試官問:「你的興趣愛好是什麼?」這樣回答,面試官最滿意
    有的人好靜, 有的人好動, 有的人喜歡獨處,有的人喜歡團隊活動,這些都可以在個人的興趣愛好中找到答案。面試官問你有什麼體育運動方面的愛好,他可不是想尋找球友,而是想從側面了解你的工作精力和活力以及身體健康程度。面試官問你是否喜歡看書,他可能是想從側面看看你是否愛好學習。
  • 你知道面試官喜歡問了什麼嗎?我已經解決了三個問題
    作者重新點燃石頭編輯彼崖我經常聽到同事和朋友們抱怨面試官的問題太難回答了。我笑著說,不是面試官問的問題難,而是你在回答的過程中不知道如何展現自己的優勢,所以沒有被面試官接受。只要我們能輕易地找到面試官的訣竅,我們就可以輕而易舉地贏得面試官的青睞。
  • 職場經驗談:面試如何說我的優缺點
    求職面試時,面試官經常會問一個問題:「請簡單說一下你的優點和缺點。」對於這個問題,網絡上流行著很多答題策略,有的職場新人直接套用,把「自己的優缺點」流利地背誦出來。小編提醒職場新人,在回答此類問題時切忌死記硬背,要根據職位特點有針對性地回答。下面我們來看看面試如何說優缺點。
  • 面試官:口字加一撇,組成什麼字?小夥兒:我能答三個
    面試官:口字加一撇,組成什麼字?小夥兒:我能答三個職場面試是能否順利就業的敲門磚,很多面試者與自己心儀的工作錯之交臂,都會抱怨是被面試官在面試過程中出的奇葩問題給「刁難」了,其實面試官並非無理取鬧之輩,他們問這些問題,反而是為了更好的篩選出崗位最適合的人才,而特定的問題。感覺到難,答不出來,只能說明你不適合這個崗位。
  • 上來就是「請自我介紹」,遇到這樣的面試官我就沒什麼興趣了
    當你與面試官面對面坐下的時候,是否遇到過某些面試官上來第一句話就是「先做一個自我介紹吧」?職場新人遇到這樣的提問肯定會非常緊張,以至於不知道怎麼開始介紹自己,而對於職場老油條來說,同樣也會一時不知所措。如果我遇到提這種問題的面試官,我心裡第一印象就是對這個面試官沒什麼興趣了。
  • 面試官問你的缺點,別再答「追求完美」,高情商這樣說才會被錄用
    恩雅說,失敗的原因就出在最後一個問題上。有過面試經歷的人應該都有體會,許多面試官會問求職者:「你覺得自己最大的缺點是什麼?」許多人面對這個問題,會有以下幾種常見的錯誤回答,這樣答很容易讓面試官不滿意。01 說的缺點是職場人的「硬傷」「我的缺點,就是有點懶,拖延症比較嚴重。」「我的缺點是時間觀念比較差。」
  • 面試時,面試官問你有什麼優點和缺點?應該如何巧妙地回答?
    工作多年,被面試過很多次,也面試過很多人,其中有一次印象最深刻,這次我不是主面試官,經理要面試一個候選人,他就拉上了我,作為陪襯,用經理的話說就是撐撐場面, 所以問題的主要是我們經理。當問到一個問題:「你有什麼優點」, 求職者巴拉巴拉說了一堆,然後又問了:「你有什麼缺點?」
  • 面試必問6大問題,自我介紹和職業規劃這樣回答,面試官滿意錄取
    這6大面試官必問面試問題,這樣回答可以拿到一份滿意的offer: 1 面試官會想通過這個問題來看你對自我的一個認識。求職者有什麼優點可以實事求是的表達,注意不要加以誇大,有什麼缺點也可以面對,在表達自己有什麼缺點後,要加以說明自己已經認識到這個缺點了,準備如何去改善。
  • 當面試官問到「你的優點/缺點是什麼」,該如何完美地回答?
    通過具體的例子展示自己的優點很多人在回答優點問題的時候過於籠統,之前面試過一個女生,她的回答「我學習能力強,工作總遇到不懂就會問,我一定會努力學習,早日成為一名優秀的內容運營。」這樣的回答肯定就涼涼了。
  • 面試官:「談談你的缺點」,別老實回答,聰明人會這樣說
    而當你能夠面試的時候,就可以了解到,面試官會根據你的簡歷情況詢問你一些問題,要是你的回答是讓他比較滿意的話,則會根據其他求職者的情況進行對比,綜合考慮下來,選擇自己最適合的人選。那麼,如果你要是面試的機會比較多,就能夠知道,面試官所提的一些問題,其實是很相似的。
  • 女面試官:我肚子疼,能幫我倒杯熱水嗎?帥哥巧妙破解被錄取
    都說現在的選拔是人才的選拔,所謂人才就是雙商在線的人,只是學會專業知識卻沒有發散性思維和以己度人的情商很難博得面試官的青睞。思維高度決定了一個人的行為高度,為了測試應聘者的行動力,面試官們想出了很多平時想都不敢想的題目。
  • 面試官:太平洋中間是什麼?白雲飛這樣回答
    面試官:太平洋中間是什麼?白雲飛這樣回答現在很多人都反應,自己很優秀,學歷很高,工作經驗豐富,態度也很好,但就是找不到心儀的工作,總是去面試後就沒有下文了。其實,一個人不管再怎麼優秀,如果不掌握面試的技巧,沒辦法再面試的時間裡把自己的優秀展現出來,那都是徒勞無功的。所以,如何在面試中表現自我,讓面試官留下印象,是求職過程中非常重要的一件事。
  • 面試官問「你還有什麼問題」?別傻問治療的問題,高情商人們會問
    在面試過程中,每個人都在盡力表現自己,在面試官面前展現自己最完美的一面,他們對一些專業問題有充分的準備,他們的答案可以到達面試官的滿意。當面試官問「你還有什麼問題」時,如何回答才能讓面試官換個角度看自己?大多數人對這個問題有兩種反應,要麼說不,要麼問無關緊要個問題。
  • 面試官:森林裡有一條眼鏡蛇從來不咬人,為什麼?我回答過被淘汰
    我們去一家公司面試,如果問你工作,對公司的期望這些問題,你可能提前預習過,能侃侃而談,勝券在握,可要是讓你回答「如何把2元的礦泉水賣到100元」,「如何把梳子賣給和尚?」這些智力題,你就支支吾吾的卡殼了。一「卡殼」發揮的效果也會不好,最後只能被心儀的公司「等電話通知」了。
  • 男面試官:「你知我深淺,我知你鬆緊」你是怎麼理解這句話的?
    男面試官:「你知我深淺,我知你鬆緊」你是怎麼理解這句話的?現如今,隨著虛擬經濟的快速發展,技術的變革,商業模式也隨之日新月異,而相對應的實體經濟,好似不是那麼的樂觀,似乎有隨時被取代的意思,而對於企業來說,危機無處不在,如何才能在這場危機安然度過?一時間成了不少企業家思考的話題。
  • 面試官:法海想自殺,白娘子說那你咬我一口吧,為什麼?小夥智答
    面試官:法海想自殺,白娘子說那你咬我一口吧,為什麼?面試官的問題是:法海想自殺,白娘子說那你咬我一口吧,為什麼第一位面試者進去之後,面試官把問題說了一下,讓面試者回答,剛聽到問題之後,面試者有點不明所以,不知道面試官是個什麼意思,她覺得是有點對自己羞辱了,因為這都不是面試中會問到的問題,她說道:「這個問題我不知道,但是我覺得我是過來面試的,不是回答你們的這種無聊的問題的
  • 當面試官問你優缺點的時候 他想問的到底是啥?
    如果面試官問,「你的優點和缺點是什麼?」請務必放大你的優點,同時,縮小——但真實反映——你的缺點。在需要毛遂自薦時,你必須具體說明。我們來想像一下:假設有兩名求職者,A和B都想應聘客服經理。輪到B了,他在這個問題上卡殼了。「我實在想不出一個缺點。」他開口說道。「或許我還不夠專注。我的優點大概是擅長與人打交道。我性格相當隨和,一般不容易生氣。」分析:1、這個答案以一個否定句開頭,看起來就像在耍小聰明,類似於——我的缺點就是沒有缺點。
  • 面試官問你的缺點是什麼,應該如何回答?
    面試官問你缺點,其實考核的智商和情商,不是真的要答案。你要給予,別人需要的。提供一個萬能公式:缺點=正能量+自嗨缺點+幽默赤裸裸的回答,缺點是愛睡懶覺。好歹這樣說:我周末喜歡睡懶覺,在平日忙碌的工作中,難得偷個懶,好繼續新一周的奮鬥。這樣的回答,面試官樂呵了,感覺你挺幽默,給你加雞腿。換種套路,肯定明智很多,情商瞬間炸裂。以此此類推,參考回答的缺點,不懂拒絕、喜歡較真。
  • 面試官:地球自轉24小時,那自轉半圈是多少個小時?王東鵬這樣說
    面試官:地球自轉24小時,那自轉半圈是多少個小時?王東鵬這樣說面試現在已經成為了,每個職場人必經的一條路了,不經歷職場面試的考驗,你都不好意思說你是個合格的職場人。確實現在的面試有點太困難了,不僅會考察面試者的學識,而且還會考察面試者的思維能力。或者是考察一些臨場反應的題目,以此來觀察面試者的個人素質。王東鵬是今年剛大學畢業的應屆生,和很多畢業生一樣,剛畢業領到畢業證,他就開始逛人才市場,投簡歷,前不久她收到了一家大型公司的面試邀請。他有點興奮,在面試這天,他很早就到公司了,他發現,這天來面試不止他一個。
  • 面試官:如何將冰箱賣給愛斯基摩人?小夥回復一句,直接被錄取
    忘記我還有一家公司了,趕緊的,趕緊去招聘一些人才過來,儘快讓公司運轉起來!「鄧主任翻了翻白眼,心想:老闆終於清醒了,我也得去做點實事了……1.「您這不是強買強賣嗎?」鄧主任接到了李老闆給面試者的面試題目,雖然也有點摸不著頭腦,但他還是乖乖去做了。