Google面試題搜尋之星和最多連續數的子集答案
這是一道Google面試題,暫且叫它“搜尋之星”吧。
給你一天的Google搜尋日誌,你怎麼設計演算法找出是否有一個搜尋詞,它出現的頻率佔所有搜尋的一半以上?如果肯定有一個搜尋詞佔大多數,你能怎麼提高你的演算法找到它?再假定搜尋日誌就是記憶體中的一個陣列,能否有O(1)空間,O(n)時間的演算法?
最多連續數的子集之參考答案
題目:
給一個整數陣列, 找到其中包含最多連續數的子集,比如給:15, 7, 12, 6, 14, 13, 9, 11,則返回: 5:[11, 12, 13, 14, 15] 。最簡單的方法是sort然後scan一遍,但是要o(nlgn),有什麼O(n)的方法嗎?
分析:
我們先來學習一種叫做並查集的資料結構。
並查集(Disjoint set或者Union-find set)是一種簡單的用途廣泛的演算法和資料結構。並查集是若干個不相交集合,能夠實現較快的合併和判斷元素所在集合的操作,應用很多,如其求無向圖的連通分量個數等。
並查集可以方便地進行以下三種操作:
1、Make_Set(x) 把每一個元素初始化為一個集合
初始化後每一個元素的父親節點是它本身,每一個元素的祖先節點也是它本身(也可以根據情況而變)。
2、Find_Set(x) 查詢一個元素所在的集合
查詢一個元素所在的集合,其精髓是找到這個元素所在集合的祖先。這個才是並查集判斷和合並的最終依據。
判斷兩個元素是否屬於同一集合,只要看他們所在集合的祖先是否相同即可。
合併兩個集合,也是使一個集合的祖先成為另一個集合的祖先,具體見示意圖。
3、Union(x,y) 合併x,y 所在的兩個集合
合併兩個不相交集合操作很簡單:
利用Find_Set找到其中兩個集合的祖先,將一個集合的祖先指向另一個集合的祖先。如圖
並查集的優化:
1、Find_Set(x)時 路徑壓縮
尋找祖先時我們一般採用遞迴查詢,但是當元素很多亦或是整棵樹變為一條鏈時,每次Find_Set(x)都是O(n)的複雜度,有沒有辦法減小這個複雜度呢?
答案是肯定的,這就是路徑壓縮,即當我們經過"遞推"找到祖先節點後,"回溯"的時候順便將它的子孫節點都直接指向祖先,這樣以後再次Find_Set(x)時複雜度就變成O(1)了,如下圖所示;可見,路徑壓縮方便了以後的查詢。
2、Union(x,y)時 按秩合併
即合併的時候將元素少的集合合併到元素多的集合中,這樣合併之後樹的高度會相對較小。
有了背景知識,我們來看如何利用它來解決這個問題。
首先,Make_Set(x)將每個元素變成一個並查集,然後掃描,Union(x-1, x),Union(x, x+1)。
接下來的問題是怎麼快速找到x-1,x+1的位置?那麼需要引入查詢為常數複雜度的雜湊表。
其他網友建議的解決方案
網友Mike建議 :
用一個map,它的key是一個起始的數字,value是這個起始數字起連續的個數。這樣這個陣列遍歷一遍下來,只要map維護好了,自然就能得到最長的連續子串了,並且演算法複雜度應該是O(n)。(不考慮map函式實現的複雜度)
前面說了維護好map就可以了,那麼怎麼來維護這個map呢?
取出當前的整數,在map裡看一下是否已經存在,若存在則直接取下一個,不存在轉2 (為什麼要看是否已經存在,因為題目沒有說不會有重複的數字。) 檢視下map裡面當前數字的前一個是否存在,如果存在,當前的最長長度就是前一個最長長度+1 檢視下map裡面當前數字的後一個是否存在,如果存在,那麼就將以下一個數字開始的子串的最後一個更新下,因為本來沒有連上的2個子串,因為當前數字的出現連起來了 接著再看下前面數字是否存在,如果存在,就更新以這個數字結尾的子串的第一個數字的連續子串長度,原因同上
演算法就是如上所示了,我們拿例子演練一遍。
1) 首先給定15,這個時候map裡面沒有15也沒有14和16,那麼這個執行完了之後map是map[15] = 1;
2) 然後遇到7,同上,也沒有6,7和8,所以執行玩了之後變成map[7]=1, map[15]=1;
3) 12同上,map[7]=1, map[12]=1, map[15]=1;
4) 接下來是6,6就不一樣了,因為7存在的,所以執行上面第3步之後,map[6]=2,map[7]=2,map[12]=1,map[15]=1;
5) 14的情況跟6一樣,結果是map[6]=2,map[7]=2,map[12]=1,map[14]=2,map[15]=2;
6) 13的情況相對複雜一些,因為12和14都存在了 ,所以它會執行以上1,2,3,4的所有4步:首先12存在,所以13的最長子串是2,14存在,所以會更新到14起始的最後一個數字的最長長度,這裡就是15的長度=它自己的加上13的長度,也就是4,同時我們把13的長度也改成4,最後因為12存在,我們要更新以12結尾的連續子串的開始處,本例中就是12自己,12對應更新成4。
7) 最後是11,11的前面一個數字不存在,後一個數字存在,也就是要執行以上1,3,第3步結束的時候已經是11和15都更新成5了。最後的結果也就是5,並且是從11起始的。
網友xd_jackfeng建議:
設定一個bitmap,初始值為0,如果出現則設定為1,這樣看有多少個1連續就可以了。
本文來自微信:待字閨中,7月2日釋出,原創@陳利人 ,歡迎大家繼續關注微信公眾賬號“待字閨中”。
相關文章
- 最多連續數的子集及單連結串列和之戀分析及解答
- Google面試題 | 不包含連續1的非負整數Go面試題
- 又見Google搜尋之星;及須彌之境分析Go
- 蓄水池抽樣及Google搜尋之星分析Go
- 熟悉的陌生人;及又見Google搜尋之星分析Go
- 搜尋引擎面試題面試題
- 關於google搜尋欄首字母粘連問題Go
- Google搜尋大法Go
- Google搜尋API?GoAPI
- Google搜尋技巧Go
- Java面試題和答案Java面試題
- 搜遍全網,整理的MySQL面試題,附答案。MySql面試題
- 快速使用Google搜尋Go
- GOOGLE搜尋祕籍Go
- google搜尋語法Go
- 百度和優酷的搜尋體驗改善,類似Google Instant搜尋Go
- Google的個性化搜尋Go
- Google 按圖搜尋的原理Go
- 面試題36:二叉搜尋樹與雙向連結串列面試題
- hive生成連續的時間和連續的數Hive
- 使用Google百度等搜尋引擎的常用搜尋技巧Go
- Google推出面部搜尋Go
- 諷刺&Google搜尋APIGoAPI
- 面試必備,Linux面試題和答案!Linux面試題
- Google Trends:2016年搜尋VR成人片最多的城市是赫爾辛基GoVR
- 最全MySQL面試題和答案(三)MySql面試題
- 最全MySQL面試題和答案(四)MySql面試題
- 阿里面試題BIO和NIO數量問題附答案和程式碼阿里面試題
- 轉:google搜尋聯盟與adsense搜尋廣告的區別Go
- 常見的 PHP 面試題和答案分享PHP面試題
- 尋找連續或不連續的子字串字串
- 圖書搜尋:Google 和 Open Content AllianceGo
- Google人工智慧面試·真·題(附參考答案+攻略)Go人工智慧面試
- 面試手撕(一):圖搜尋,排布問題面試
- Google搜尋指令大全(最新整理)Go
- 黃了。Google中國版搜尋Go
- google搜尋你想知道的東西Go
- Mashable:Google搜尋背後的資料Go