一.
有
15
個瓶子,其中最多有一瓶有毒,現在有四只
老鼠,喝了有毒的水之后,第二天就會死。如何在第二天就可以判斷出哪個瓶子有毒。
解答:
四只老鼠,用二進制可以給瓶子編碼0001 - 1111
;
具體操作:
這里我們將水瓶依次編號為1 - 15
, 老鼠依次編號為1 - 4
;每只老鼠分別喝下對應二進制位為1的水,最后根據老鼠的死亡情況,可以定位到哪一瓶水有毒。
比如說老鼠3
和老鼠4
都死了,就證明是第3瓶
水有毒。
二.
六個海盜搶到共計100個寶石,現在由第一個海盜開始輪流提出分贓計劃,只要同意計劃的人不超過一半,提出計劃的海盜會被處死,然后下個人繼續提出計劃。如果海盜無法獲得認可的最大利益,那么一定會投反對。請問第一個海盜如何提出分贓計劃,保證自己的利益最大化并且不死?
解:逆向推導題目:以最小的支出爭取可以爭取的人。
2人: 【0 - 100】
3人: 【99 - 1 - 0】
4人: 【97 - 0 - 2 - 1】
5人: 【97 - 0 - 1 - 0 - 2】
6人:【96 - 0 - 1 - 2 - 1 - 0】
當只剩下
2個
海盜,海盜1
和海盜2
,由海盜1
來提出分贓計劃,海盜1
只能是自己得0個金幣
,海盜2
分得100金幣
,這樣才能保證自己不會被處死。當只剩下
3個
海盜,海盜1
、海盜2
、海盜3
,由海盜1
來提出分贓計劃,海盜1
給出的分贓計劃是海盜1
為99
金幣,海盜2
位1金幣
,海盜3
為0金幣
,這個計劃海盜1
和海盜2
肯定同意,超過一半,海盜2
之所以會同意是因為當只剩下海盜2
和海盜3
的時候,海盜2
來提出分贓計劃,海盜2
一個金幣都沒有,所以海盜2
會同意這個計劃。當只剩下
4個
海盜,海盜1、海盜2、海盜3、海盜4
,由海盜1
來提出分贓計劃,海盜1
提出的分贓計劃是海盜1
為97
金幣,海盜2
為0
金幣,海盜3
為2
金幣,海盜4
為1金幣
,之所以這么分配是依據只有3個海盜
的情況來判斷,對于海盜2
來說,如果只有3個海盜
,他可以分得99個金幣
,所以干脆給他0個金幣
;海盜3
,如果只有3個海盜
可以分得1個金幣
,所以給他2個金幣
,海盜2
肯定同意,海盜4
,如果只有3個海盜
可以分得0個金幣
,所以給他1個金幣
,他也會同意。這樣就會超過一半的人同意這個方案。當只剩下
5個
海盜,海盜1提出的分贓計劃是海盜1
為97
個金幣,海盜2
為0個
金幣,海盜3
為1個金幣
,海盜4
為0個金幣
,海盜5
為2個金幣
,這樣就能保證超過一半的人同意這個計劃。當只剩下
6個
海盜時,海盜1
提出的分贓計劃是海盜1
為96個
金幣,海盜2
為0個
金幣,海盜3
為1個金幣
,海盜4
為2個金幣
,海盜5
為1個金幣
,這樣就能保證超過一半的人同意這個計劃。
三.
有
100
個人搶紅包,每6
個人可以成組領取共計3
元紅包,每個人限領3
次,請問100
個人最多可以領取多少錢?
解:
首先100
個人中找出4
個人,稱作A4
,其余96人
組成16
組領取紅包。接著從96
個人中找出4
個,稱作B4
,A4
和另外92
個人組成16
組領取紅包。再從剩下92
個人里面找出4人
稱作C4
,A4+B4+88
人組成16
組領取。最后剩下領取了兩次的A4、B4、C4
一起組成兩組,領取紅包,每個人都領取三次,共計領取150
元
四.
假設有
10GB
的訂單數據,我們希望按照訂單金額(假設金額都是正整數
)進行排序,但是內存有限只有100M
,沒辦法一次性將10GB
的數據都加載到內存中,請問要怎么進行排序。
解:
先將
10GB
的數據,分成100
份,每份100M
,然后分段加載進內存,遍歷統計訂單金額所在范圍,假設統計范圍為0 - 10萬
之間,我們將所有的訂單依據訂單金額劃分為100
個桶,第一個桶的金額為0 - 1000
元, 第二個桶是1001 - 2000
元,以此類推,每個桶對應一個存儲文件,并且按照金額范圍大小順序編號命名(00, 01, 02, ... 99)
;然后再次分段遍歷
10GB
的訂單數據,將依據訂單金額,將訂單放入對應的桶中,然后存儲到相應的磁盤上,如果訂單金額分布比較均勻,那每個桶最終的訂單大小差不多是100M
左右,但也可能出現相差較大的現象,那就將桶中訂單數據大小超過100M
的繼續在該桶金額范圍內繼續劃分,直到每個桶的訂單數據大小,小于100M
。然后依次加載每個桶的訂單數據,依據訂單金額,對數據從小到大進行排序。
五.
在一個文件中有
10G
個整數,亂序排列,要求找出中位數
。內存限制為2G
。只寫出思路即可(內存限制為2G
的意思就是,可以使用2G
的空間來運行程序,而不考慮這臺機器上的其他軟件的占用內存)。
解:
思路: 一個整數占4
個字節,每個字節是8
位,將整形的每1
位作為一個關鍵字,如果最高位值越大,整數越大,如果最高位相同再比較次高位。整個比較過程類似于字符串的字典排序。
將
10G
整數分成5
次,每次2G
讀入內存,然后遍歷讀入內存的數據,對每個數據利用位運算取出最高的8
位(24 - 31
),這8bi
t最多可以表示255
個桶,因此依據最高8bit
的值,將整數放入對應的桶中。最后把每個桶寫入磁盤中,同時在統計每個桶中的整數數量,并存儲。依據內存中統計的每個桶的整數數量,計算中位數在哪個桶中,然后對這個桶進行排序,取出中位數的值。
如果中位數所處的桶的大小超過2G,那么就對這個桶里面的數據依據
次高8位
繼續進行劃分(16- 23
),并統計各個桶中的數量,然后依據之前算成來的桶的數量進行計算,算成中位數處于哪個桶,并對該桶進行排序,取出中位數。
六.
假設我們有 10 萬條 URL 訪問日志,如何按照訪問次數給 URL 排序?
解:
遍歷
10
萬條數據,以URL
作為Key
,訪問次數作為Value
,存入散列表,同時記錄下訪問次數的最大值k
,時間復雜度O(N)
;如果
K
不是很大,可以使用桶排序
,時間復雜度是O(N)
,如果K
非常大,就使用快速排序,時間復雜度為O(nlogn)
;
七.
有兩個字符串數組,每個數組大約有
10
萬條字符串,如何快速找出兩個數組中相同的字符串。
- 以第一個字符串數組構建
HashSet
,key
為字符串,再遍歷第二個字符串數組,以字符串為key
在HashSet
查找,如果包含就說明存在與該字符相同的字符串,添加到相同列表里面。
八.
假設獵聘網有
10
萬名獵頭,每個獵頭都可以通過做任務(比如發布職位)來積累積分,然后通過積分來下載簡歷。假設你是獵聘網的一名工程師,如何在內存中存儲這10
萬個獵頭ID
和積分信息,讓它支持如下操作:
根據獵頭的
ID
快速查找、刪除、更新這個獵頭的積分信息。查找積分在某個區間的獵頭
ID
列表;查找按照積分從小到大排名在
第x位
到第y位
之間的獵頭ID列表。
解:
以
獵頭ID
構建一個散列表
,以積分排序
構建一個跳表
ID
在散列表中所以可以O(1)
查找到這個獵頭積分
以跳表
存儲,跳表
支持區間查詢
九.
區塊鏈使用的是哪種哈希算法嗎?是為了解決什么問題而使用的呢?
解:
區塊鏈
是一塊塊區塊組成的,每個區塊分為兩部分:區塊頭
和區塊體
。區塊頭
保存著自己的區塊體
和上一個區塊頭
的哈希值
因為這種
鏈式
關系和哈希值
的唯一性,只要區塊鏈上任意一個區塊被修改過,后面所有區塊保存的哈希值就不對了。區塊鏈使用的是
SHA256
哈希算法,計算哈希值非常耗時,如果要篡改一個區塊,就必須重新計算后面所有區塊的哈希值,短時間幾乎不可能做到。