一、演算法設計
1、設rand(s,t)返回[s,t]之間的隨機小數,利用該函式在乙個半徑為r的圓內找隨機n個點,並給出時間複雜度分析。
void getnpointsincircle(int r, int n)
}
極座標思路:
在半徑為r的圓內找隨機的n個點,既然是找點,那麼就需要為其建立座標系,如果建立平面直角座標系,以圓心為原點,建立半徑為r的圓的直角座標系。要使隨機的點在圓內,則必須使其所找的點 point 的x,y座標的絕對值小於r,問題轉化為:隨機的找n個圓內的點,使其x,y座標的絕對值均小於r。這裡以x為例, 首先 x 應滿足 -r<= x <= r; y同理。這樣產生的點均在以圓心為中心,邊長為2r的正放形內,需要另外判斷其距離r的值。本文介紹採用極座標的形式,建立圓的極座標系,則圓內的任意一點滿足p(ρ,θ)(用ρ表示線段op的長度,θ表示從ox到op的角度angle),此時問題轉化為:找一點,使其到圓心的距離op大於等於0 小於r,極角大於等於0 小於360,則op=rand(0, r) ,當 op== r 時重新尋找,angle = rand(0,360) ,當angle==360時,重新尋找。每找到乙個點p,將其與之前所找到的所有點進行比較,若重合,則繼續尋找,否則將其加入到已找到的點集合中,直到找到n個點。
[cpp]view plain
copy
print?
存放點的資料結構
typedef
struct pointpoint;
演算法流程:
for( i=n ; i >0; i--)
產生 p.r = rand(0,r),且p.r != r
產生 p.rangle = rand(0,360) ,且 p.rangle != 360
遍歷所有產生的點,若 p 已經存在,則重新生成該點
否則將其加入到產生的點集合中
存放點的資料結構
typedef struct pointpoint;
演算法流程:
for( i=n ; i >0; i--)
產生 p.r = rand(0,r),且p.r != r
產生 p.rangle = rand(0,360) ,且 p.rangle != 360
遍歷所有產生的點,若 p 已經存在,則重新生成該點
否則將其加入到產生的點集合中
生成第n個點,需要先遍歷前n-1個點,時間複雜度為o(n),故生成n個點的時間複雜度為o(n^2)
2、為分析使用者行為,系統常需儲存使用者的一些query,但因query非常多,故系統不能全存,設系統每天只存m個query,現設計乙個演算法,對使用者請求的query進行隨機選擇m個,請給乙個方案,使得每個query被抽中的概率相等,並分析之,注意:不到最後一刻,並不知使用者的總請求量。
蓄水池抽樣問題
隨機抽樣問題表示如下:
要求從n個元素中隨機的抽取k個元素,其中n無法確定。
這種應用的場景一般是資料流的情況下,由於資料只能被讀取一次,而且資料量很大,並不能全部儲存,因此資料量n是無法在抽樣開始時確定的;但又要保持隨機性,於是有了這個問題。所以搜尋**有時候會問這樣的問題。
【解決】
解決方案就是蓄水庫抽樣(reservoid sampling)。主要思想就是保持乙個集合(這個集合中的每個數字出現),作為蓄水池,依次遍歷所有資料的時候以一定概率替換這個蓄水池中的數字。
//偽碼
init: a reservoir with the size:k
for i= k+1 to n
{
m = random(1, i);if (m解釋一下:程式的開始就是把前k個元素都放到水庫中,然後對之後的第i個元素,以k/i的概率替換掉這個水庫中的某乙個元素。
【證明】
(1)初始情況。出現在水庫中的k個元素的出現概率都是一致的,都是1。這個很顯然。
(2)第一步。第一步就是指,處理第k+1個元素的情況。分兩種情況:元素全部都沒有被替換;其中某個元素與第k+1個元素交換。
我們先看情況2:第k+1個元素被選中的概率是k/(k+1)(根據公式k/i),所以這個新元素在水庫中出現的概率就一定是k/(k+1)(不管它替換掉哪個元素,反正肯定它是以這個概率出現在水庫中)。下面來看水庫中剩餘的元素出現的概率,也就是1-p(這個元素被替換掉的概率)。水庫中任意乙個元素被替換掉的概率是:(k/k+1)*(1/k)=1/(k+1),意即首先要第k+1個元素被選中,然後自己在集合的k個元素中被選中。那它出現的概率就是1-1/(k+1)=k/(k+1)。可以看出來,舊元素和新元素出現的概率是相等的。
情況1:當元素全部都沒有替換掉的時候,每個元素的出現概率肯定是一樣的,這很顯然。但具體是多少呢?就是1-p(第k+1個元素被選中)=1-k/(k+1)=1/(k+1)。
(3)歸納法:重複上面的過程,只要證明第i步到第i+1步,所有元素出現的概率是相等的即可。
1. 1)c++中vector中pushback內部是如何實現的?
push_back函式在容器尾部建立乙個新元素,並使容器長度加1。新元素為括號中元素的副本。
3、c++ stl中vector的相關問題:
(1)、呼叫push_back時,其內部的記憶體分配是如何進行的?
(2)、呼叫clear時,內部是如何具體實現的?若想將其記憶體釋放,該如何操作?
push_back函式在容器尾部建立乙個新元素,並使容器長度加1。新元素為括號中元素的副本。
百度2011 10 16校園招聘會筆試題
一 演算法設計 1 設rand s,t 返回 s,t 之間的隨機小數,利用該函式在乙個半徑為r的圓內找隨機n個點,並給出時間複雜度分析。思路 這個使用數學中的極座標來解決,先呼叫 s1,t1 隨機產生乙個數r,歸一化後乘以半徑,得到r r s1 t1 s1 然後在呼叫 s2,t2 隨機產生乙個數a,...
百度2011 10 16校園招聘會筆試題
一 演算法設計 1 設rand s,t 返回 s,t 之間的隨機小數,利用該函式在乙個半徑為r的圓內找隨機n個點,並給出時間複雜度分析。void getnpointsincircle int r,int n 極座標思路 在半徑為r的圓內找隨機的n個點,既然是找點,那麼就需要為其建立座標系,如果建立平...
百度2011 10 16校園招聘會筆試題
一 演算法設計 1 設rand s,t 返回 s,t 之間的隨機小數,利用該函式在乙個半徑為r的圓內找隨機n個點,並給出時間複雜度分析。思路 這個使用數學中的極座標來解決,先呼叫 s1,t1 隨機產生乙個數r,歸一化後乘以半徑,得到r r s1 t1 s1 然後在呼叫 s2,t2 隨機產生乙個數a,...