3 回答
TA貢獻(xiàn)1936條經(jīng)驗(yàn) 獲得超7個贊
首先,從解釋和代碼中可以很清楚地看出作者所設(shè)定的含義,就像他們寫的一樣。在實(shí)際的實(shí)現(xiàn)中,可以將集合建模為數(shù)組,這并不意味著任何事情。在編程方面的挑戰(zhàn)中,人們通常使用相當(dāng)簡單的結(jié)構(gòu)-如數(shù)組代替java.util.Set。
因此,任務(wù)基本上是:
M從size數(shù)組中隨機(jī)選擇一組元素N。
假設(shè)N >= M。
現(xiàn)在最困難的部分:為什么該算法會產(chǎn)生正確的結(jié)果?
僅看算法,很難理解它是如何工作的以及為什么。我認(rèn)為這是因?yàn)樗惴▽?shí)際上是遞歸構(gòu)造的,而遞歸finall在迭代中沒有展開。
讓我們從遞歸開始。
假設(shè)我們能夠M從size數(shù)組中隨機(jī)選擇元素N - 1。我們?nèi)绾蜯從大小數(shù)組中選擇元素N?
由于數(shù)組中有一個“新”元素,因此我們可以用其中的一個替換選定的元素-或保留原樣。但是我們必須保留隨機(jī)屬性。
可以從中選擇一組M元素??梢詮闹羞x擇 一組元素。N-1(N-1)! / M!*(N-1 - M)!
MNN! / M!*(N - M)!
這意味著我們應(yīng)該保留(N-M)/N概率集,并用概率替換元素之一M/N。我們還必須選擇要用1/M概率替換的元素。
讓我們看看它在代碼中的外觀。假設(shè)subset是我們從中隨機(jī)選擇的一組M元素N-1。
首先,我們應(yīng)該決定是否替換其中一個元素。我們需要一個(N-M)/N概率。為此,我們可以在0和之間生成一個隨機(jī)數(shù)N。如果該數(shù)字小于M,我們將替換。
boolean replace = rand(random, 0, N) < M;
if (replace) {
// then replace
}
現(xiàn)在我們必須選擇要替換的元素之一。由于我們將數(shù)組建模為一個集合,因此我們可以簡單地在0和之間M - 1(包括兩者之間)隨機(jī)選擇一個索引。這樣我們得到:
boolean replace = rand(random, 0, N) < M;
if (replace) {
subset[rand(random, 0, M - 1)] = original[N];
}
在這里我們可以注意到,如果我們的第一個隨機(jī)值(rand(random, 0, N))小于M,則它是0和之間的一個隨機(jī)值M-1。因此,我們不需要第二個rand:
int r = rand(random, 0, N);
boolean replace = r < M;
if (replace) {
subset[r] = original[N];
}
其余的應(yīng)該是微不足道的。
遞歸的基本情況是M == N。在這種情況下,我們什么都不會替換,因此所選元素的集合就是原始數(shù)組的簡單形式。
之后,可以將遞歸簡單地編碼為一個循環(huán)。i代表N每個步驟-這為您提供了自己的代碼。
TA貢獻(xiàn)1852條經(jīng)驗(yàn) 獲得超1個贊
我認(rèn)為作者想說我們需要生成的不是set而是array。
不,作者真正的意思是集合,但碰巧將結(jié)果集合存儲在數(shù)組中。通過說結(jié)果是一個集合,就意味著值的順序無關(guān)緊要,這意味著{1, 2}和{2, 1}是相同的集合。
鑒于此,它是確定這一結(jié)果永遠(yuǎn)不會{2, 1},只要結(jié)果與值的概率1和2為1/6,即無序臺(套)的概率。
如果您想要一個有序的結(jié)果,即列出它們時有12個不同的結(jié)果,那么最簡單的解決方案是改組原始數(shù)組并采用第一個M值。這樣可以保證所有結(jié)果的概率均等,并且不會重復(fù)。
通常使用Fisher-Yates shuffle來進(jìn)行數(shù)組改組,這是對數(shù)組進(jìn)行迭代并將該元素與先前的元素隨機(jī)交換。
問題中的算法是該算法的一種變體。如果跳過前M個值的隨機(jī)改組,則順序無關(guān)緊要。然后,它會隨機(jī)地將后續(xù)元素與隨機(jī)元素交換,但是如果隨機(jī)位置> M不會發(fā)生交換,并且交換掉的值將被簡單丟棄,因?yàn)樗罱K會出現(xiàn)在結(jié)果集之外。
因此,這是經(jīng)過修改的Fisher-Yates隨機(jī)播放,可以在原始數(shù)組的副本中生成隨機(jī)子集,但是經(jīng)過優(yōu)化,可以跳過不必要的隨機(jī)播放,因?yàn)槲覀冃枰粋€集合,而不是有序列表/數(shù)組,而我們只想要一個子集,而不是所有值。
TA貢獻(xiàn)1799條經(jīng)驗(yàn) 獲得超8個贊
如何用數(shù)學(xué)證明呢?
您的第二個for循環(huán)運(yùn)行兩次,首先i等于2,然后i等于3。
當(dāng)i為2時,r變?yōu)?、1或2,每個概率為1/3。因此,chara將以索引0或1或根本不索引的形式移到您的結(jié)果中,每個概率為1/3?,F(xiàn)在它是[a,2],[1,a]或[1,2]。
當(dāng)i為3時,r為0、1、2或3。b以1/4的概率移至索引0,以1/4的概率移至索引1,并且沒有以1/2的概率移至任何位置。
在下表中,我給出了所有可能情況下的結(jié)果。值下r,0,1和2,是在第一次迭代(可能的值i= 2)。右邊的或是r第二次迭代中的可能值。
r 0 1 2 3
0 [b, 2] [a, b] [a, 2] [a, 2]
1 [b, a] [1, b] [1, a] [1, a]
2 [b, 2] [1, b] [1, 2] [1, 2]
因此,在表中您可以讀取到,如果r兩次都為0,則您的方法將返回[b, 2],等等。
表中的12個單元格中的每個單元具有相等的概率,即1/12。讓我們檢查一下:[1,2],[1,a],[1,b],[a,2]和[b,2]分別存在兩次。[a,b]和[b,a]各自出現(xiàn)一次,但是它們是同一集合,因此該集合也出現(xiàn)兩次。這涵蓋了所有可能的子集,因此它們的可能性也相同。
添加回答
舉報
