如何使用递归方法在C#中创建随机唯一数

本文关键字:创建 随机 唯一 何使用 递归方法 | 更新日期: 2023-09-27 18:20:49

我正在尝试生成5个1-10之间的随机数,这些随机数没有重复值。因此,我创建了一个递归方法,该方法应该检查为数组中的任何位置创建的值是否已经使用过。如果有,那么它将创建一个新的随机数并再次检查。

这是我的代码:

    static Random randomObject = new Random();
    static void Main(string[] args)
    {
    long[] randomArr = new long[5];

    for (int i = 0; i < randomArr.Length; i++ )
    {
        if (randomArr[i] == randomArr[0])
        {
            randomArr[i] = randomObject.Next(1, 11);
        }
        else 
        {
            long check = randomObject.Next(1, 11);
            randomArr[i] = CheckIfUnique(check, randomArr);
        }
    }
    Console.WriteLine("'nPress the [enter] key to continue...");
    Console.ReadLine();
}
static long CheckIfUnique(long a, long[] b) 
{
    for (int i = 0; i <= b.GetUpperBound(0); i++) 
    {
        if (a == b[i])
        {
           a = randomObject.Next(1, 11);
           CheckIfUnique(a, b);
        }
    }
    return a;
}

但我仍然得到重复的值。有人知道我的逻辑中是否有错误,或者编译器在经过这么多递归步骤后是否会崩溃吗?

如何使用递归方法在C#中创建随机唯一数

注意-这不是一个递归的答案


你真的可以让这变得更容易:

static Random randomObject = new Random();
static void Main(string[] args)
{
    long[] randomArr = new long[5];
    for (int i = 0; i < randomArr.Length;)
    {
        long t = randomObject.Next(1, 11);
        if(CheckIfUnique(t, randomArr, i))
        {
              randomArr[i++] = t;
        }
    }
}
static bool CheckIfUnique(long a, long[] b, int length)
{
    for (int i = 0; i < length; i++) 
    {
        if (a == b[i])
        {
           return false
        }
    }
    return true;
}

这样,循环直到有足够的随机值,但只有在生成新的唯一值后才推进计数器。

您的方法非常繁重。作为一种变体,您可以看到这种方法。不过,如果你愿意,我可以试着纠正你的算法。数字的顺序是原始的,由Random类创建:

HashSet<int> origNumbers = new HashSet<int>();
Random rnd=new Random();            
do
{
   int k = rnd.Next(10);
   origNumbers.Add(k);
}
while (origNumbers.Count <5);

更新(感谢@AlexeiLevenkov):

如果添加元素的顺序很重要,则最好使用集合SortedSet<T>Random类创建的数字顺序按升序排序,它不是Random类创建的顺序:

SortedSet<int> origNumbers = new SortedSet<int>();
Random rnd=new Random();            
do
{
   int k = rnd.Next(10);
   origNumbers.Add(k);
}
while (origNumbers.Count <5);

这里有一个非常简单的解决方案:

var random = new System.Random(Guid.NewGuid().GetHashCode());  
var values = Enumerable.Range(0, 10).OrderBy(x => random.Next()).Take(5).ToArray();

它不是递归的,但除非它是家庭作业,否则递归不会很好地用于您的案例

在这种情况下,假设如下:

1) 无重复

2) 的可能值范围相对较小(最多几百?)

我会用你所有可能的值填充一个小的初始数据集,然后从中选择:

    static Random randomObject = new Random();
    static void Main(string[] args)
    {
        int MAX_NUMBER = 10;
        int MIN_NUMBER = 1;
        int NUMBER_OF_RESULTS_REQUIRED = 5;
        long[] randomArr = new long[NUMBER_OF_RESULTS_REQUIRED];
        //Use a pool of all possible values
        List<long> dataSet = new List<long>();

        for (int i = MIN_NUMBER; i <= MAX_NUMBER; ++i)
        {
            dataSet.Add(i);
        }
        for (int i = 0; i < NUMBER_OF_RESULTS_REQUIRED; ++i)
        {
            int t = randomObject.Next(0, dataSet.Count);
            randomArr[i] = dataSet[t];
            dataSet.RemoveAt(t);
        }
        for (int i = 0; i < randomArr.Length; ++i)
        {
            Console.WriteLine(randomArr[i]);
        }
        Console.ReadKey();
    }