Генератор случайных чисел в C # – уникальные значения

Я занят в C # с кодированием массива. Я могу заполнить его случайными генераторами, но теперь я задаю вопрос, как это сделать, но чтобы я мог проверить, уже ли это значение в массиве и если оно генерирует новое значение

Дополнительная информация:
Максимальное значение: 100
Количество элементов: 100

ВАЖНАЯ ПЛЖСКАЯ РАБОТА ДАЛЬШЕ НА МОЕЙ ИДЕИ

моя идея

public void FillArray(int[] A, int Range) { for (int I = 0; I < A.Length; I++) { A[I] = ValidNumber(T, I, Range); } } /* Fill Array */ 

Реализация сортировки

 public void SelectionSort(int[] A) { int K, X; for (int I = 0; I < A.Length - 1; I++) { K = I; X = A[K]; for (int J = I + 1; J < A.Length; J++) { if (A[J] < X) { K = J; X = A[K]; } } A[K] = A[I]; A[I] = X; } } /* Selection sort */ 

Это всего лишь некоторые идеи, теперь я хочу знать, как я могу это исправить, поэтому я могу смотреть с выбором сортировки, если там есть allread there (fillarray), который является таким же, если это заменит его новым случайным значением. И поэтому я хочу создать случайный массив с ints – от 1 до 100 в случайном порядке

как это сделать, но чтобы я мог проверить, уже ли это значение в массиве, и если это так генерирует новое значение

Вы этого не делаете, потому что это очень плохая идея .

Чтобы проиллюстрировать, почему это ужасная идея, рассмотрите другую версию той же проблемы: соберите миллион чисел в случайный порядок следующим процессом:

  1. Выберите число от одного до миллиона.
  2. Проверьте, нет ли в списке.
  3. Если это так, вернитесь к шагу 1
  4. В противном случае добавьте номер в список.
  5. Есть ли в списке один миллион предметов? Если да, то все готово. Если нет, вернитесь к шагу 1.

Ясно, что это работает. Это хорошая идея? Предположим, вы почти закончили. В списке есть 999999 элементов. Единственный недостающий элемент – 857313. Что вы делаете? Вы выбираете случайное число, скажем, 12. Теперь вы проверяете элементы 999999 в списке, чтобы увидеть, есть ли кто-либо из них 12. 12, возможно, был одним из первых чисел, которые вы выбрали, поэтому его можно было бы быстро найти. Или это может быть один из последних, так что это займет много времени. В среднем на 500000 проверок будет показано, есть ли 12 в списке. И это так, поскольку в списке осталось только одно число.

12 не получилось. Вернитесь к началу. Выберите другое случайное число, скажем, 53259. Это в списке? Еще полмиллиона чеков.

Продолжайте делать это до тех пор, пока вы не сгенерируете 857313, что случается каждый миллион попыток.

Итак, в среднем, для размещения последнего элемента в списке берется 500000 x 1000000 = пятьсот миллиардов сравнений. Это может пойти еще больше. Это может занять несколько триллионов сравнений. Или вам повезет, и это займет один. Но в среднем, пол триллиона сравнений.

Это ужасный способ создать случайный порядок списка.

Есть два хороших способа сделать случайный порядок списка.

(1) Создайте устройство, которое может сортировать список с заданной функцией заказа. Обеспечьте стабильное упорядочение, основанное на случайном семени.

Обратите внимание, что вы не должны создавать случайный порядок, создавая метод, который возвращает случайные результаты, когда его спрашивают: «A больше B?» Это неустойчивое упорядочение; многие алгоритмы сортировки основаны на стабильном упорядочении сортировки и будут входить в бесконечные циклы или иметь другое плохое поведение при задании неустойчивого упорядочения сортировки.

Этот алгоритм O (n lg n) и обладает хорошим свойством, что очень легко написать из стандартных частей, как указывают другие ответы. Это также чрезвычайно быстро для небольших списков в типичных реализациях.

(2) Выбирайте элемент по индексу из списка источников в случайном порядке, удаляя его из исходного списка по ходу и помещая его в список адресатов.

Последний известен как Knuth Shuffle или Fischer-Yates Shuffle, и это очень быстрый алгоритм. Вы можете сделать это «на месте», мутируя существующий массив в перетасованный порядок или создавая новый список. У этого также есть хорошая собственность, которую вы можете «заплатить за игру», перетасовывая «верх» списка, когда вам это нужно. Если у вас есть миллион предметов для перетасовки, но вам нужна только первая сотня, вы можете просто разработать порядок сортировки для первой сотни и назвать это хорошим.

Ниже будет создан массив с номерами 1-100 в случайном порядке.

  Random rnd = new Random(); var randomNumbers = Enumerable.Range(1, 100).OrderBy(i => rnd.Next()).ToArray(); 

Из вашего описания я считаю, что вам нужен массив из 100 целых чисел со значениями от 1 до 100 и без дубликатов чисел. Если числа являются целыми числами, вам не нужно генерировать случайные числа, так как все возможные числа находятся в массиве. Таким образом, только порядок или числа могут быть рандомизированы.

Используя подход Linq и Jesper Palm – с помощью Томаса Левеска следующее утверждение даст вам необходимый вам массив.

 Random rnd = new Random(); var randomNumbers = Enumerable.Range(1, 100) .Select(x => new { val = x, order = rnd.Next() }) .OrderBy(i => i.order) .Select(x => x.val) .ToArray(); 

Метод даже довольно быстрый, определенно более эффективный, чем любые операции сравнения.

Чтобы объяснить сказанное выше на оригинальный плакат, см. Комментарий ниже:

  • Enumerable.Range(1, 100) создает диапазон целых чисел, начинающийся с 1 и заканчивающийся на 100.
  • .Select(x => new { val = x, order = rnd.Next() }) создает новый временный объект, содержащий значение и позицию заказа, которая определяется случайным числом.
  • .OrderBy(i => i.order) сортирует временные объекты по порядку.
  • .Select(x => x.val) выбирает значение временного объекта, таким образом преобразуя его обратно в int.
  • .ToArray() снова возвращает все в массив.

Используемый синтаксис – это LINQ, который доступен в .NET 3.5. С более старыми версиями, которые вы wold, нужно реализовать самостоятельно, что намного сложнее и дольше.

Следуя замечанию Эрика: Если вы хотите переустановить, вы можете сделать код следующим образом

 var list = myInputList; var result = list.Select(x => new { val = x, order = rnd.Next() }) .OrderBy(i => i.order) .Select(x => x.val) .ToArray(); 

Вот наивная реализация:

 int[] values = new int[100]; Random random = new Random(); for(int i = 0; i < values.Length; i++) { int v; do { v = random.Next(100) + 1; } while (Array.IndexOf(values, v) != -1) values[i] = v; } 

Но это было бы довольно неэффективно, особенно ближе к концу массива ...

Лучшим решением было бы рассмотреть это, так как вы хотите, чтобы 100 различных значений от 1 до 100 в случайном порядке, ваш массив в конечном итоге будет содержать все возможные значения от 1 до 100. Таким образом, вам просто нужно создать последовательность этих значений и «перетасовать» его:

 int[] values = Enumerable.Range(1, 100).ToArray(); Random random = new Random(); for(int i = values.Length - 1; i > 0; i--) { int j = random.Next(i + 1); int tmp = values[i]; values[i] = values[j]; values[j] = tmp; } 

EDIT: лучший подход, который должен работать для менее конкретных случаев:

 T[] RandomCombinationWithNoRepeat(IEnumerable itemsToPickFrom, int numberOfItemsToPick) { // Copy original items to pick from, because we need to modify it List itemsCopy = new List(itemsToPickFrom); T[] array = new T[numberOfItemsToPick]; Random random = new Random(); for(int i = 0; i < numberOfItemsToPick; i++) { // Pick item and remove it from list int index = random.Next(itemsCopy.Count); array[i] = itemsCopy[index]; itemsCopy.RemoveAt(index); } return array; } 

В вашем случае вы будете использовать его так:

 int[] result = RandomCombinationWithNoRepeat(Enumerable.Range(1, 100), 100); 

из того, что я понял. Вам понадобится набор целых чисел со случайными числами. Я предполагаю, что использование int array или List of int не имеет значения. Вот простой полный подход, который вы описали.
using System; using System.Collections.Generic; using System.Text;

namespace FillRandom {class Program {static void Main (string [] args) {int minValue = 1; int maxValue = 100; // создаем список int с емкостью, установленной как 100 List array = new List (100);

  FillArray(array, minValue, maxValue, array.Capacity); //print out all values in the array foreach (int i in array) { Console.WriteLine(i); } } private static void FillArray(List array, int minValue, int maxValue, int capacity) { int count = 0; while (array.Count != capacity - 1) { Random rnd = new Random(); int value = rnd.Next(minValue, maxValue); if (!array.Contains(value)) { array.Add(value); } count++; } //print out the number of times the looping occurs Console.WriteLine("count: "+count); } } 

}

Вы можете создать проект консоли и попробовать.

Давайте будем гением компьютера.