1. 程式人生 > 其它 >springboot專案釋出全流程

springboot專案釋出全流程

給定一個數據流,資料流長度N很大,且N直到處理完所有資料之前都不可知,請問如何在只遍歷一遍資料(O(N))的情況下,能夠隨機選取出m個不重複的資料。

這個場景強調了3件事:

  1. 資料流長度N很大且不可知,所以不能一次性存入記憶體。
  2. 時間複雜度為O(N)。
  3. 隨機選取m個數,每個數被選中的概率為m/N。

面試中被問到的概率題,才想起學習一下,這篇部落格總體參考大佬的部落格,但是在證明那裡加入了自己的理解。

演算法思路:

  1. 如果接收的資料量小於m,則依次放入蓄水池。
  2. 當接收到第i個數據時,i >= m,在[0, i]範圍內取以隨機數d,若d的落在[0, m-1]範圍內,則用接收到的第i個數據去替換蓄水池中的第d個數據。
  3. 重複步驟2。

演算法的精妙之處在於:當處理完所有的資料時,蓄水池中的每個資料都是以m/N的概率獲得的。

演算法證明:

i個接收到的資料最後能夠留在蓄水池中的概率=第i個數據進入過蓄水池的概率*之後的i+1N操作裡第i個數據不被替換的概率(第i+1到第N次處理 資料i都不會被替換)。

  1. i<=m時,資料直接放進蓄水池,所以第i個數據進入過蓄水池的概率=1
  2. i>m時,在[1,i]內選取隨機數d,如果d<=m,則使用第i個數據替換蓄水池中第d個數據,因此第i個數據進入過蓄水池的概率=m/i
  3. i<=m時,程式從接收到第m+1個數據時開始執行替換操作,第m+1次處理會替換池中資料的概率為m/(m+1),在池中執行替換 替換掉第i個數據的概率為1/m,則第m+1次處理替換掉第i個數據的概率為(m/(m+1))*(1/m)=1/(m+1),不被替換的概率為1-1/(m+1)=m/(m+1)。依次,第m+2次處理不替換掉第i個數據概率為(m+1)/(m+2)...第N次處理不替換掉第i個數據的概率為(N-1)/N。所以,之後第i
    個數據不被替換的概率=m/(m+1)*(m+1)/(m+2)*...*(N-1)/N=m/N
  4. i>m時,程式從接收到第i+1個數據時才開始有可能替換第i個數據。則參考上述第3點,第i+1個數據對蓄水池裡的每個資料d進行替換的概率=m/(i+1) *1/m=1/(i+1),假設i在蓄水池中,i不被i+1替換的概率為1- 1/(i+1)=i/(i+1),所以之後的N-i個操作裡第i個數據不被替換的概率=i/(i+1)*(i+1)/(i+2)*…*(N-1)/N=i/N
  5. 結合第1點和第3點可知,當i<=m時,第i個接收到的資料最後留在蓄水池中的概率=1*m/N=m/N。結合第2點和第4點可知,當i>m時,第i個接收到的資料留在蓄水池中的概率=m/i*i/N=m/N。綜上可知,每個資料最後被選中留在蓄水池中的概率為m/N