Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/275.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 不重复的数字列表_C# - Fatal编程技术网

C# 不重复的数字列表

C# 不重复的数字列表,c#,C#,我需要打印从1到99的随机数,不要重复。 下面的代码给出了堆栈溢出 int newNumb= Random.Range(1, 99); if(acum.Count > 0) { while (acum.Contains(newNumb)) { newNumb= Random.Range(1, 99); } } 最好的方法是生成所有必要的数字,并从列表中提取,直到其为空,创建一个新的顺序;这通常被称为洗牌 您当前的代码花费的时间太长,您需要跟踪已选

我需要打印从1到99的随机数,不要重复。 下面的代码给出了堆栈溢出

int newNumb= Random.Range(1, 99);
if(acum.Count > 0)
{
    while (acum.Contains(newNumb))
    {
         newNumb= Random.Range(1, 99);
    }
}

最好的方法是生成所有必要的数字,并从列表中提取,直到其为空,创建一个新的顺序;这通常被称为洗牌

您当前的代码花费的时间太长,您需要跟踪已选择的数字,并且只从剩余的数字中进行选择。在psudocode中

generate list
while list not empty
    choose number from list
    remove it from list
    add to new list
这样做很简单:

var list = new List<int>();
for (int i = 0; i < 99; i++)
{
    list.Add(i);
}

var resultList = list.OrderBy(i => Guid.NewGuid());
使现代化 这种解决方案似乎效率低下。请使用菲舍尔·耶茨(fischer yates)洗牌(如@Joel的回答所示)。

非有效方式(见评论):

Random rand=new Random();
HashSet randomHashSet=新HashSet();
while(randomHashSet.Count<99)
randomHashSet.Add(rand.Next(1100));
List randomList=randomHashSet.ToList();
更新

有效途径:

Random r = new Random();
var result = Enumerable.Range(1, 99).ToList();
for (int i = 0, j = r.Next(0, 99); i < 99; i++, j = r.Next(0, 99))
    result[i] = result[i] + result[j] - (result[j] = result[i]); // Swap
Random r=new Random();
var result=Enumerable.Range(1,99).ToList();
for(inti=0,j=r.Next(0,99);i<99;i++,j=r.Next(0,99))
结果[i]=结果[i]+结果[j]-(结果[j]=结果[i]);//交换

此问题的典型解决方案是生成从1到99的顺序范围,然后将其洗牌:

static Random\u Random=new Random();
公共静态无效洗牌(IList项)
{
对于(int i=thisList.Count-1;i>0;i--)
{
int j=_random.Next(0,i);
T tmp=项目[i];
项目[i]=项目[j];
项目[j]=tmp;
}
}
var numbers=Enumerable.Range(1,99).ToList();
洗牌(数字);
foreach(数值中的变量编号)
{
控制台写入线(编号);
}

这将生成一个随机整数列表,每次生成一个不同的整数,并将其添加到列表中。

洗牌法更好,但由于范围非常有限,也可以丢弃重复的数字。

超过100次运行,使用秒表()测量运行时间,列表生成从未超过200次。
在我的计算机上,已洗牌的列表显示5次(1029~1395次)。

如果列表计数设置为>值,则范围上限(在本例中为100+),则生成过程当然永远不会结束。没有足够的不同随机值来填充列表。

Random random = new Random();

    List<int> acum = new List<int>();

    while (acum.Count < 99)
    {
        int Number = random.Next(1, 100);
        if (!acum.Contains(Number))
        {
            acum.Add(Number);
        }
    }
Random Random=new Random();
List acum=新列表();
而(acum.Count<99)
{
整数=random.Next(1100);
如果(!acum.Contains(Number))
{
acum.Add(数字);
}
}
要验证结果,请对列表进行排序,并查看其顺序从1到99:

List<int> acum2 = acum.OrderBy(n => n).ToList();
List acum2=acum.OrderBy(n=>n.ToList();


shuffle一个包含从1到99的所有数字的列表。你不可能从该代码中得到堆栈溢出。你会怎么做?@Charleh,你可能是对的,但你仍然可以得到堆栈溢出,只要假设你知道acumOr的类型<代码>可枚举。范围(0,99)并避免loop@CamiloTerevinto,添加到答案中,谢谢。排序时,算法将通过一个序列比较成对的值,并可能交换它们。此代码为每次比较生成一个新的guid。假设序列包括数字13、30和45。比较13和30是可能的,所以13是第一位的。然后比较30和45,让30排在第一位(13,然后30,然后45),然后再比较13和45,让45排在13之前。真糟糕。不要这样做。编写一个真正的fischer-yates shuffle并不难。想想
i=>Guid.NewGuid()
表达式的作用。当排序算法需要比较两个值时,这是它用来(对两个值)确定如何比较这些值的代码。因此,每次在执行
OrderBy()
的过程中进行任何比较时,它都会再次生成一个全新的guid,即使之前已经对该值进行了比较。在洗牌中,这将是好的。。。但是
OrderBy()
是为了生成有序的结果而编写的,这可能会导致它到达陌生的地方,并且需要花费比需要更长的时间才能到达那里。这就是为什么javascript的排序算法要求使用一个函数来查看两个值(
a
b
),而不是只查看一个
i
),函数只进行比较的地方。。。完美的你所说的确实有效,但为什么我的代码会给我堆栈溢出对于(int j=1;j<100;j++){int newNumb=Random.Range(1,9);if(acum.Count>0){while(acum.Contains(newNumb)){nuevo=Random.Range(1,9);}}}acum.Add(newNumb)}`@Nogerad不知道,你不应该得到堆栈溢出,但是你的片段将永远运行,因为只有8个数字[1,9],而你正试图强制执行100个唯一的数字。解决方法是什么?这将复制很多数字。这将非常缓慢,你可能会生成成千上万个无用的数字否,Hashset不允许重复@HusseinGolshani不,你不明白,每一个副本都会被忽略,这段代码可能会永远运行。虽然这段代码效率低下,但这不仅仅是CPU周期问题,这个解决方案也会导致同样的问题,潜在的堆栈溢出。答案中的代码将OP中的
Contains
调用替换为查找重复项的
HashSet
,但结果相同。拿你的代码来说,想象一下RNG一直在生成
1
。发生了什么?我想你可以在
I>0
停止
for
循环。当
i==0
时,您将调用
random。下一个(0,0)
将返回0。用
items[0]
交换
items[0]
本身并没有错,但您实际上不需要这样做。@FrankBoyne已修复,谢谢。使用c不是更好吗
static Random _random = new Random();

public static void Shuffle<T>(IList<T> items)
{
    for (int i = thisList.Count - 1; i > 0; i--)
    {
        int j = _random.Next(0, i);
        T tmp = items[i];
        items[i] = items[j];
        items[j] = tmp;
    }
}

var numbers = Enumerable.Range(1,99).ToList();
Shuffle(numbers);
foreach (var number in numbers)
{
     Console.WriteLine(number);
}
Random random = new Random();

    List<int> acum = new List<int>();

    while (acum.Count < 99)
    {
        int Number = random.Next(1, 100);
        if (!acum.Contains(Number))
        {
            acum.Add(Number);
        }
    }
List<int> acum2 = acum.OrderBy(n => n).ToList();