BAT面試大資料筆記
大資料
Map-Reduce 和Hadoop 逐漸成為面試熱門
1. 介紹雜湊函式
雜湊函式又叫雜湊函式
1.1 典型的雜湊函式都有無限的輸入值域。
1.2 輸入值相同時,返回值一樣。
1.3 輸入值不同時,返回值可能一樣,也可能不一樣
1.4 不同輸入值得到的雜湊值,整體均分的分佈在輸出域S上(重要)
1~3 點性質是雜湊函式的基礎,第4點是評價一個雜湊函式優劣的關鍵。
aaa1 aaa2 aaa3 雖然相似,但雜湊值差異巨大。
2.介紹Map-Rdeduce
2.1 Map階段 把大任務分成子任務
2.2 Reduce階段 子任務併發處理,然後合併結果。
難點:工程上的處理
注意點:
1. 備份的考慮,分散式儲存的設計細節,以及容災策略。
2. 任務分配策略與任務進度跟蹤的細節設計,節點狀態的呈現
3. 多使用者許可權的控制
map-reduce 方法統計文章的單詞
文章-> 預處理
1.去掉標點符號
2.連字元
3.對於縮寫的處理
4.大小寫的處理
對每個單詞生成詞頻為1
雜湊函式
子任務進行處理
海量數量處理技巧
- 分而自治,通過雜湊函式將大任務分流到機器或分流秤小檔案
- 常用hashMap 或bitamp
難點:通訊、時間和空間的估算。
- 請對10億個IPV4的ip地址進行排序,每個ip只會出現一次。
普通做法:
ip-轉換為無符號整數 10億個整數 4G
推薦做法:
bitmap 2^32 bit型別的陣列。
每個位置上是一個bit,只能表示0和1兩種狀態。
長度為2^32的bit陣列,空間約為128m.
請對10億人的年齡進行排序
0~200
計數排序20億全是32位數整數的檔案,空間限制大小2G
hashmap記錄所有出現的次數
key->具體某一種數
value-> 這種數出現的次數
記憶體可能超出
檔案分流
在40億個無符號整數的檔案,所以在整個範圍中必然沒有出現過的數,可以使用最多10M的記憶體,只用找到一個沒有出現過的數即可,該如何找?
hash 表 40億條 每一條4個位元組 16G
bitmap 500M
64個區間
500M/64 8M
1、根據記憶體限制決定區間大小,根據區間大小,得到有多少個變數,來記錄每個區間的數出現的次數。
2、 統計區間上的數的出現次數,找到不足的區間。
3、利用bitmap對不滿足的區間,進行這個區間上的數的詞頻統計。
百億資料中,找到100個熱詞
分流 確定機器數
對每一個機器,進行檔案分流,小根堆 確定top100
工程師使用伺服器叢集來設計和是吸納資料快取,以下是常見的側臉。
- 無論是新增、查詢還是刪除資料,都先將資料的id通過雜湊函式轉換成一個雜湊值,記為key.
2.如果目前機器有N臺,則計算key%N的值,這個值就是該資料所屬的機器編號,無論是新增、刪除還是查詢操作,都只在這臺機器上進行。請分析這種快取策略可能帶來的問題。並提出改進的方案。
如果增加或刪除機器,資料遷移的代價很大。
一致性雜湊演算法
資料id—> 0~ 2 ^32
key 和data 相鄰儲存
順時針進行
動態規劃
給定陣列arr,arr中所有的值杜偉整數且不重複。每個值代表一種面值的貨幣,每種面值的貨幣可以使用任意張,再給定一個整數aim代表要找的錢數,求換錢有多少種方法.
暴力搜尋方法
記憶搜尋方法
動態規劃方法
狀態繼續優化
arr={5,10,25,1} aim={1000}
- 暴力搜尋解決:
public int coins1(int[] arr,int aim){
if(arr==null||arr.length==0||aim<0)
{
return 0;
}
return process1(arr,0,aim);
}
public int process1(int [] arr,int index,int aim){
int res=0;
if(index==arr.length){
res=aim==0?1:0;
}else{
for(int i=0;arr[index]*i<=aim;i++){
res+=process1(arr,index+1,aim-arr[index]*i);
}
}
}
如果已經使用0張5元和1張10元的情況下
後續將求:p1(arr,2,990)
這裡2表示arr剩下的錢為arr[2,3] 即為[25,1]
990:表示要找的剩餘錢數。
2張5元0張10元p1(arr,2,990)
記憶搜尋方法:
arr={5,10,24,1}, aim=1000
p(index,aim) 結果表map每計算完一個p(index,aim),都將結果放入map中,index和aim組成共同的key,
返回結果為Value.要進入一個遞迴過程p(index,aim)
先以index和aim註冊的key在map中查詢是否已經在value中,如果存在,則直接取值,如果不存在,才進行遞迴計算。
public int coins2(int[] arr,int aim){
if(arr==null||arr.length==0||aim<0){
return 0;
}
int[][] map=new int[arr.length+1][aim+1];
return process2(arr,0,aim,map);
}
public int process2(int[] arr,int index,int aim,int[][] map){
int res=0;
if(index==arr.length){
res=aim==0?1:0;
}else{
int mapValue=0;
for(int i=0;arr[index]*i<=aim;i++){
mapValue=mapValue==-1?0:mapValue;
}else{
res+=process2(arr,index+1,aim-arr[index]*i,map);
}
}
}
map[index][aim]=res==0?-1:res;
return res;
}
動態規劃方法
如果arr長度為N,生成行數為N,列數為aim+1的矩陣dp
dp[i][j] 的含義是在使用arr[0..i]貨幣的情況下,有多少種方法。
什麼是動態規劃方法
其本質是利用空間來記錄每一個暴力搜尋的計算結果的時候直接使用,從而不再是用重複計算。
動態規劃由於規定了每一種遞迴的計算順序,依次進行計算。
面試中遇到暴力遞迴題目可以優化成動態規劃方法的大體過程:
- 實現暴力遞迴方法。
- 在暴力搜尋方法的函式中看看那些引數可以代表遞迴過程。
- 找到代表遞迴過程的引數之後,記憶話搜尋方法非常容易實現。
- 通過分析記憶話搜尋的依賴路徑,進而實現動態規劃。
- 根據記憶化搜尋方法改出動態規劃,減少時間複雜度。
動態規劃的關鍵點:
最優化原理,也就是最優子結構性質。這指的是一個最優化策略具有這樣的性質,不論過去狀態和決策如何,對前面的決策所形成的的狀態而言,餘下的諸多決策必須構成最優決策,簡單來說就是一個最優化的策略的子策略總是最優的,如果一個問題滿足最優化原理,就稱其具有最優子結構性質。
無後效性。指的是某狀態下決策的收益,只與狀態和決策相關,與到達該狀態的方式無關。
子問題的重疊性,動態規劃將原來具有指數級時間複雜度的暴力搜尋演算法改進成了具有多項式時間複雜度的演算法。其中的關鍵在於解決冗餘,這是動態規劃演算法的根本目的。
經典動態規劃的問題
有n級臺階,一個每次上一級或者兩級,問有多少種走完n級的方法?
f(1)=1
f(2)=2
f(i)= f(i-1)+f(i-2)
public int s1(int n){
if(n<1)
return 0;
}
if(n==1||n==2){
return n;
}
return s1(n-1)+s1(n-2);
}
求矩陣中最小的路徑和
dp[i][j]=m[i][j]+dp[i-1][j]
dp[i][j-1]返回arr的最長遞增子序列長度
2 1 5 3 6 4 8 9 7
返回 1 3 4 8 9 長度為5arr 2 1 5 3 6 4 8 9 7
dp: 1 1 2 2 3 3 4 5 4 長度為5假設str1的長度為M,str2的長度為N,生成大小為M*N的矩陣dp.dp[i][j]的含義是str1[0..i] 與str2[0..j]的最長公共序列的長度。
待補:
一個揹包有一定的承重W,有N件物品,每件都有自己的價值,記錄在陣列V中,也都有自己的重量,記錄在陣列W中,沒見物品只能選擇要裝入揹包還是不裝入揹包,要求在不超過揹包承重的前提下,選出物品的總價值最大。
假設物品編號1~n,一件一件物品考慮是否加入揹包
假設dp[x][y]表示前X件物品,不超過重量y的時候的最大價值。列舉一下第X件物品的情況。
情況一: 如果選擇第X件物品,則前X-1件物品得到的重量不能超過y-w[x].
情況二:如果不選第X件物品,則前X-1件物品得到的重量不能超過所以dp[x][y]可能等於dp[x-1][y],也就是是不取第x件物品的時候,價值和之前一樣。 也可能是dp[x-1][y-w[x]]+v[x], 也就是決定拿第x件物品的情況,當然會獲得x物品的價值。 兩種可能性中,應該選擇價值最大的那個。dp[x][y]=max{dp[x-1][y],dp[x-1][y-w[x]]+v[x]}. 對於dp矩陣來說,行數是物品的數量n,行數是揹包的重量W。從左到右,再從上到下依次計算所有dp值即可。