2013-02-14 100 views
0

我想用1-10的隨機數填充數組,並且不重複。我試圖用遞歸來做到這一點。我試圖與遞歸和沒有(這裏是兩個,沒有任何運氣)。我有兩個代碼,boths不工作:隨機填充一個數組,不需要重複

1:

static int reco(int arr,int[] times) 
{ 
    Random rnd = new Random(); 
    arr = rnd.Next(1, 11); 
    return times[arr] > 0 ? reco(arr, times) : arr; 
} 

static void Main(string[] args) 
{ 
    int i = 0; 
    int[] arr = new int[10]; 
    int[] times = new int[11]; 
    Random rnd = new Random(); 

    for (i = 0; i < 10; i++) 
    { 
     arr[i] = rnd.Next(1, 11); 
     times[arr[i]]++; 

     if (times[arr[i]] > 0) 
      arr[i] = reco(arr[i], times); 
    } 

2:

static int reco(int arr,int[] times) 
{ 
    Random rnd = new Random(); 
    arr = rnd.Next(1, 11); 
    if (times[arr] > 0) 
     return reco(arr, times); 
    else 
     return arr; 
} 
static void Main(string[] args) 
{ 
    int i = 0; 
    int[] arr = new int[10]; 
    int[] times = new int[11]; 
    Random rnd = new Random(); 
    for (i = 0; i < 10; i++) 
    { 
     arr[i] = rnd.Next(1, 11); 

     if (times[arr[i]] > 0) 
      arr[i] = reco(arr[i], times); 

     times[arr[i]]++; 
    } 
} 
+0

請說明你的分析,它是「不工作」。 – 2013-02-14 22:16:45

+1

如果你的意思是以隨機順序填充數組0..N,那麼標準的做法是首先用數組0..N填充數組,然後迭代數組並交換每個數組價值與另一個在陣列中的隨機位置 - 即洗牌。 – 2013-02-14 22:19:31

回答

0
static void Main() 
    { 
     int[] arr = new int[10]; 
     List<int> numbers = Enumerable.Range(1, 10).ToList(); 
     Random rnd = new Random(); 
     for (int i = 0; i < 10; i++) 
     { 
      int index = rnd.Next(0, numbers.Count - 1); 
      arr[i] = numbers[index]; 
      numbers.RemoveAt(index); 
     } 
    } 
+1

儘管此解決方案適用於小型陣列,但請考慮如果您嘗試使用它來洗牌一百萬個元素會發生什麼情況。你的程序需要多長時間才能運行? – 2013-02-14 22:39:23

+0

@EricLippert - 同意先生!但是對於大範圍的解決方案是什麼? – 2013-02-14 22:44:05

+1

Knuth-Fischer-Yates洗牌。 – 2013-02-14 23:55:57

4

如果你只想1到10之間的隨機數,你可以只需使用Enumerable.Range並隨機訂購。

var ran = new Random(); 
int[] randomArray = Enumerable.Range(1, 10).OrderBy(x => ran.Next()).ToArray(); 
+2

Guid不是隨機性的來源;他們是唯一性的來源。 guid生成器被允許生成連續的guid。 **如果你沒有使用唯一的GUID,你做錯了什麼。** – 2013-02-14 22:37:40

+0

@EricLippert,我會發現它Guid.NewGuid()吐出一大串順序GUIDS奇怪,但我看到你的觀點,並更新我的答案使用隨機:) – 2013-02-14 22:49:29

+0

所有新的GUID保證你有一個極高的概率,生成的GUID是唯一的。 (有些情況下,即使是第1版guid也不是唯一的。)第4版guid是僞隨機的,但不能保證guid生成器會生成第4版guid。許多guid生成器在當天生成順序版本1 guid。 – 2013-02-14 23:58:26

2

生成特定範圍內等獨特的 「隨機」 數:

List<int> theList = Enumerable.Range(0, 10).ToList(); 
theList.Shuffle(); 

輸出示例:

[1,5,4,8,2,9,6,3,7,0] 

隨機功能(來源:Randomize a List<T>):

public static void Shuffle<T>(this IList<T> list) 
{ 
    Random rng = new Random(); 
    int n = list.Count; 
    while (n > 1) { 
     n--; 
     int k = rng.Next(n + 1); 
     T value = list[k]; 
     list[k] = list[n]; 
     list[n] = value; 
    } 
} 
+2

到目前爲止,這是唯一的解決方案,它既是均勻分佈的(就隨機產生均勻分佈的程度而言),而且對於任意大小的列表而言都是有效的。 – 2013-02-14 22:41:08

+0

我會傳入'Random'的實例。 「Random」的默認構造函數是按設計分解的。 – CodesInChaos 2013-02-17 13:28:53

0

你可以做到這一點。

int[] arr = new int[10]; 

// Fill the array with values 1 to 10: 
for (int i = 0; i < arr.Length; i++) 
{ 
    arr[i] = i + 1; 
} 

// Switch pairs of values for unbiased uniform random distribution: 
Random rnd = new Random(); 
for (int i = 0; i < arr.Length - 1; i++) 
{ 
    int j = rnd.Next(i, arr.Length); 

    int temp = arr[i]; 
    arr[i] = arr[j]; 
    arr[j] = temp; 
} 

這將使用Fisher-Yates (Knuth) shuffle在下面的評論中提出埃裏克利珀:因爲這個問題聽起來像是一門功課練習的遞歸版本留作一個練習了原來的海報。

+0

您的交換次數是(1)不必要的大,並且(2)不會產生均勻分佈。考慮使用Knuth shuffle來代替。 – 2013-02-14 22:40:06

+0

@EricLippert:我從來沒有聽說過這個算法。我明白它爲什麼起作用並相應地更改了代碼。 – Virtlink 2013-02-14 23:03:01

1

由於您使用的是C#,並且您知道數組中的隨機數,爲什麼不創建一個數組,然後隨機化這些位置呢?這裏是一個例子:

using System.Linq; 

//...... 

Random rand = new Random(); 
int[] randomNumbers = new int[10] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; 
randomNumbers.OrderBy(num => rand.Next());