3 回答

TA貢獻(xiàn)1936條經(jīng)驗(yàn) 獲得超7個(gè)贊
首先,從解釋和代碼中可以很清楚地看出作者所設(shè)定的含義,就像他們寫(xiě)的一樣。在實(shí)際的實(shí)現(xiàn)中,可以將集合建模為數(shù)組,這并不意味著任何事情。在編程方面的挑戰(zhàn)中,人們通常使用相當(dāng)簡(jiǎn)單的結(jié)構(gòu)-如數(shù)組代替java.util.Set。
因此,任務(wù)基本上是:
M從size數(shù)組中隨機(jī)選擇一組元素N。
假設(shè)N >= M。
現(xiàn)在最困難的部分:為什么該算法會(huì)產(chǎn)生正確的結(jié)果?
僅看算法,很難理解它是如何工作的以及為什么。我認(rèn)為這是因?yàn)樗惴▽?shí)際上是遞歸構(gòu)造的,而遞歸finall在迭代中沒(méi)有展開(kāi)。
讓我們從遞歸開(kāi)始。
假設(shè)我們能夠M從size數(shù)組中隨機(jī)選擇元素N - 1。我們?nèi)绾蜯從大小數(shù)組中選擇元素N?
由于數(shù)組中有一個(gè)“新”元素,因此我們可以用其中的一個(gè)替換選定的元素-或保留原樣。但是我們必須保留隨機(jī)屬性。
可以從中選擇一組M元素。可以從中選擇 一組元素。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)該決定是否替換其中一個(gè)元素。我們需要一個(gè)(N-M)/N概率。為此,我們可以在0和之間生成一個(gè)隨機(jī)數(shù)N。如果該數(shù)字小于M,我們將替換。
boolean replace = rand(random, 0, N) < M;
if (replace) {
// then replace
}
現(xiàn)在我們必須選擇要替換的元素之一。由于我們將數(shù)組建模為一個(gè)集合,因此我們可以簡(jiǎn)單地在0和之間M - 1(包括兩者之間)隨機(jī)選擇一個(gè)索引。這樣我們得到:
boolean replace = rand(random, 0, N) < M;
if (replace) {
subset[rand(random, 0, M - 1)] = original[N];
}
在這里我們可以注意到,如果我們的第一個(gè)隨機(jī)值(rand(random, 0, N))小于M,則它是0和之間的一個(gè)隨機(jī)值M-1。因此,我們不需要第二個(gè)rand:
int r = rand(random, 0, N);
boolean replace = r < M;
if (replace) {
subset[r] = original[N];
}
其余的應(yīng)該是微不足道的。
遞歸的基本情況是M == N。在這種情況下,我們什么都不會(huì)替換,因此所選元素的集合就是原始數(shù)組的簡(jiǎn)單形式。
之后,可以將遞歸簡(jiǎn)單地編碼為一個(gè)循環(huán)。i代表N每個(gè)步驟-這為您提供了自己的代碼。

TA貢獻(xiàn)1852條經(jīng)驗(yàn) 獲得超1個(gè)贊
我認(rèn)為作者想說(shuō)我們需要生成的不是set而是array。
不,作者真正的意思是集合,但碰巧將結(jié)果集合存儲(chǔ)在數(shù)組中。通過(guò)說(shuō)結(jié)果是一個(gè)集合,就意味著值的順序無(wú)關(guān)緊要,這意味著{1, 2}
和{2, 1}
是相同的集合。
鑒于此,它是確定這一結(jié)果永遠(yuǎn)不會(huì){2, 1}
,只要結(jié)果與值的概率1
和2
為1/6,即無(wú)序臺(tái)(套)的概率。
如果您想要一個(gè)有序的結(jié)果,即列出它們時(shí)有12個(gè)不同的結(jié)果,那么最簡(jiǎn)單的解決方案是改組原始數(shù)組并采用第一個(gè)M
值。這樣可以保證所有結(jié)果的概率均等,并且不會(huì)重復(fù)。
通常使用Fisher-Yates shuffle來(lái)進(jìn)行數(shù)組改組,這是對(duì)數(shù)組進(jìn)行迭代并將該元素與先前的元素隨機(jī)交換。
問(wèn)題中的算法是該算法的一種變體。如果跳過(guò)前M個(gè)值的隨機(jī)改組,則順序無(wú)關(guān)緊要。然后,它會(huì)隨機(jī)地將后續(xù)元素與隨機(jī)元素交換,但是如果隨機(jī)位置> M不會(huì)發(fā)生交換,并且交換掉的值將被簡(jiǎn)單丟棄,因?yàn)樗罱K會(huì)出現(xiàn)在結(jié)果集之外。
因此,這是經(jīng)過(guò)修改的Fisher-Yates隨機(jī)播放,可以在原始數(shù)組的副本中生成隨機(jī)子集,但是經(jīng)過(guò)優(yōu)化,可以跳過(guò)不必要的隨機(jī)播放,因?yàn)槲覀冃枰粋€(gè)集合,而不是有序列表/數(shù)組,而我們只想要一個(gè)子集,而不是所有值。

TA貢獻(xiàn)1799條經(jīng)驗(yàn) 獲得超8個(gè)贊
如何用數(shù)學(xué)證明呢?
您的第二個(gè)for循環(huán)運(yùn)行兩次,首先i等于2,然后i等于3。
當(dāng)i為2時(shí),r變?yōu)?、1或2,每個(gè)概率為1/3。因此,chara將以索引0或1或根本不索引的形式移到您的結(jié)果中,每個(gè)概率為1/3。現(xiàn)在它是[a,2],[1,a]或[1,2]。
當(dāng)i為3時(shí),r為0、1、2或3。b以1/4的概率移至索引0,以1/4的概率移至索引1,并且沒(méi)有以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個(gè)單元格中的每個(gè)單元具有相等的概率,即1/12。讓我們檢查一下:[1,2],[1,a],[1,b],[a,2]和[b,2]分別存在兩次。[a,b]和[b,a]各自出現(xiàn)一次,但是它們是同一集合,因此該集合也出現(xiàn)兩次。這涵蓋了所有可能的子集,因此它們的可能性也相同。
添加回答
舉報(bào)