非重複隨機序列的高效生成(C語言)
- 問題描述
- 思想+程序
閱讀之前注意:
本文閱讀建議用時:14min
本文閱讀結構如下表:
項目 | 下屬項目 | 測試用例數量 |
---|---|---|
問題描述 | 無 | 0 |
思想+程序 | 無 | 1 |
問題描述
- 有一個長度爲N的序列,現在要你把它全部打亂順序,生成一個隨機的序列
思想+程序
思路1:
- 生成隨機數,要交換的序號=隨機數%長度
- 判斷要交換的序號是否已經被交換過,若交換過則跳回步驟1重新生成隨機數,若沒有交換過則交換後再跳回步驟1,直至所有的序號都被交換過
思路2:
- 第 i 次(i 從0開始且每次遞增1)生成隨機數,要交換的序號=隨機數%(長度- i )
- 交換序號 i 和 步驟1中“要交換的序號”,直至 i 遞增到了序列末尾
通常情況下我們會想到思路1,但當N非常大時,生成的隨機數%長度 得到的序號很有可能是已經交換過的序號,導致效率很低。
而思路2通過巧妙的固定規律交換,即序號 i 是有規律遞增的,而另一個要交換的序號是序列中序號 i 之後的任意一個隨機序號,同樣實現了隨機性,且保證了時間複雜度爲O(n),十分高效!
同樣是交換,祕訣在於交換的法則。
我們用C語言實現了思路2
程序參考以下代碼:
#include<stdio.h>
#include<stdlib.h>
#define N 10
void swap(int *a, int i, int j)
{
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
void main()
{
int i = 0;
int a[N] = { 0 };
for (i = 0; i < N; i++)
a[i] = i + 1;
for (i = 0; i < N; i++)//交換a[i]和a[i]後面的隨機序號
swap(a, i, i + rand() % (N - i));
for (i = 0; i < N; i++)
printf("%d ", a[i]);
system("pause");
}
可以看到代碼部分也十分簡潔1
- 問題源於一次面試,同時感謝前輩的點撥. ↩