前N個自然數的隨機置換


來自:【數據結構與算法分析——C語言描述】練習2.7

問題描述:假設需要生成前N個自然數的一個隨機置換。例如,{4,1,2,5,2} 和 {3,1,4,2,5} 就是合法的置換,但 {5,4,1,2,1} 卻不是,因為數1出現了兩次而數 3 缺沒有。這個程序常常用於模擬一些算法。我們假設存在一個隨機數生成器 randInt(i, j) ,它以相同的概率生成 i 和 j 之間的一個整數。

 

下面是三個算法:

1.如下填入 A[0] 到 A[N-1] 的數組 A;為了填入 A[i] ,生成隨機數直到它不同於已經生成的 A[0], A[1],  ... ,  A[i-1] 時,再將其填入 A[i] 。

2.同算法1,但是要保存一個附加的數組,稱之為 Used(用過的)數組。當一個隨機數 Ran 最初被放入數組A的時候,置Used[Ran]=1。這就是說,當用一個隨機數填入 A[i] 時,可以用一步來測試是否該隨機數已經被使用,而不是像第一個算法那樣(可能)進行 i 步測試。

3.填寫該數組使得 A[i] = i + 1。然后

for(i = 1; i < N; i++) 
    swap(&A[i], &A[randInt(0, i)]);

題目中有說“我們假設存在一個隨機數RandInt(i, j)”,既然如此,暫時不必考慮其內部實現以及內存限制,只根據這個接口考慮算法即可。

 

算法1

i = 0;
while (i < N)
{
    ran = randInt(0, N);
    for (k = 0; k < i; k++)
    {
        if (A[k] == ran)
            break;
    }
    if (k == i)
    {
        A[i] = ran;
        count++;
    }
}

以循環次數作為時間度量。循環從i=0到i=n-1寫出n個不重復隨機數,因為生成第i個不重復隨機數的概率是(N-i)/N,所以理論上經過N/(N-i)次生成,得到不重復隨機數的概率為1。所以總耗時為

這里做了分子的放大,以及這個調和和公式:

該算法的時間復雜度即為O(N2logN)。

 

算法2

i = 0;
while (i < N)
{
    ran = randInt(0, N);
    if (used[ran] == 0)
    {
        A[i] = ran;
        used[ran] = 1;
        i++;
    }
}

算法 2 比算法 1 少了內層的 for 循環,所以時間復雜度降了一階,即為 O(NlogN)。

 

算法3

for (i = 0; i < N; i++)
    A[i] = i + 1;
for (i = 0; i < N; i++)
    swap(&A[i], &A[randInt(0, i)]);

時間復雜度顯然是線性級的,O(N)。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM