使用循环在数组中生成唯一的随机数
Posted
技术标签:
【中文标题】使用循环在数组中生成唯一的随机数【英文标题】:Generating Unique Random Numbers in an Array using Loop 【发布时间】:2013-10-22 03:11:00 【问题描述】:所以问题是开发一个 [5][5] 表,每个表都包含从 1 到 100 的唯一数字(没有重复)
这就是我想出的:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
int outerLoop;
int innerLoop;
int board[5][5]; /* Array Name And Size*/
/* seeds the random number generator*/
srand(time(NULL));
int number;
number = rand() % 101;
/* Start a loop to generate a random integer between 1 and 100 and
assign it into the array. The loop runs 25 times*/
for ( outerLoop = 0 ; outerLoop <= 25 ; outerLoop++ ) /* loop 25 times*/
for ( innerLoop = 0 ; innerLoop <= 4 ; innerLoop++ ) /* <=4 due to 5
columns*/
board[outerLoop][innerLoop] = rand() % 100 + 1;
printf( "%d \n", board[outerLoop][innerLoop] );
所以我几乎被困在这里。我不太确定:
board[outerLoop][innerLoop] = rand() % 100 + 1;
我只是编造的:/有什么想法吗?
【问题讨论】:
外层for循环需要为outerLoop <= 4
,否则会出现奇怪的情况。
另一个可能的灵感来源 - reservoir sampling。虽然碰巧的是,第一个显示的算法与koodawg 已经建议的基于洗牌的方法相同。
【参考方案1】:
C 以 row-major order 存储数组,即第 0 行的元素在前,然后是第 1 行的元素,依此类推。
我们可以通过将int board[5][5]
视为int board[5*5]
来利用这一点。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define N 5
int main()
int i, outerLoop = 1;
int board[N*N];
srand(time(NULL));
int number;
board[0] = rand() % 100 + 1; //initializing the first element
while(1)
number = rand() % 100 + 1 ;
if(outerLoop == N*N)
break;
else
//Cheking the previous elements for no duplicacy
for ( i = 0; i < outerLoop; i++)
if(number == board[i])
break;
//confirming whether all the elements are checked or not and the assigning number to the array element and then increment the counter outerLoop
if(i == outerLoop)
board[outerLoop] = number;
outerLoop++;
else
continue;
//Printing the elements of array board[N*N]
for ( outerLoop = 0 ; outerLoop < N*N ; outerLoop++ )
printf( "%d\t", board[outerLoop] );
if(outerLoop % N == 4)
printf("\n\n");
【讨论】:
您好先生,请问board[0] = rand() % 100 + 1; //初始化第一个元素是什么意思? 这是因为我从1
开始我的outerLoop
计数器,对于第一次迭代,if
中的条件number == board[i]
将number
与board[i]
进行比较(必须初始化在进行任何比较之前)。您可以通过简单地将 outerLoop
初始化为 0
来省略该语句 (board[0] = rand() % 100 + 1;
)。试试吧!【参考方案2】:
你想要的是一个洗牌算法
Shuffle array in C
让你的 25 个元素的唯一#s 数组从 1 到 100;只需创建一个包含数字 1..100 的 100 元素数组,将第一个 25 从 100 个池中洗牌,然后使用第一个 25。
$ cat test.c
#include <stdio.h>
#include <stdlib.h>
void shuffle(int *array, size_t array_size, size_t shuff_size)
if (array_size > 1)
size_t i;
for (i = 0; i < shuff_size - 1; i++)
size_t j = i + rand() / (RAND_MAX / (array_size - i) + 1);
int t = array[j];
array[j] = array[i];
array[i] = t;
int main(int argc, char * argv[])
int a[100];
int b[5][5];
int i,j,k=0;
for(i=0; i<100;++i)
a[i]=i;
shuffle(a,100,25);
for(i=0;i<5;++i)
for(j=0;j<5;++j)
b[i][j] = a[k++];
printf("%d ",b[i][j]);
printf("\n");
$ gcc -o test test.c
$ ./test
0 14 76 47 55 25 10 70 7 94 44 57 85 16 18 60 72 17 49 24 53 75 67 9 19
【讨论】:
经典的shuffle算法是Fisher-Yates。我认为这就是你正在做的,但我的头痛意味着我可能错了。 @Roddy - 如果未洗牌包的所有卡片都是唯一的,则洗牌只会改变顺序 - 卡片仍然是唯一的。按顺序将数组初始化为 1..25,然后随机播放。 @Steve314 - 100% 同意,但该信息需要成为答案的一部分! 如果您使用的是 Fisher-Yates,如果您只使用前 25 个值,则无需完全混洗您的 100 个值。一旦混洗已混洗前 25 个项目,它将永远不要再碰它们,所以洗牌项目 26..100 (你不会使用)有点毫无意义。对于您消耗的每个随机物品,您需要进行一次交换。您甚至可以将 shuffle 与项目的使用交错(如协程或生成器,但无需语言的帮助)。 抱歉——我的意思是你仍然洗牌 100 个项目的完整数组,但你只运行前 25 个项目的循环——交换仍然可以将值 26..100 交换到第一个—— 25 范围。要处理它,shuffle
函数需要三个参数 - 数组指针和两个大小 - 总共有多少项 (100) 以及必须正确打乱的项 (25)。【参考方案3】:
把它想象成一副 100 张牌。
创建一个包含卡号 (1..100) 的 100 元素数组 随机排列数组(=deck)。 (见@koodawg 的回答和@Steve314 的评论) 将牌组中的前 25 张牌“发给”自己,放入 5x5 阵列中。【讨论】:
【参考方案4】:由于int board[5][5];
分配了连续的内存量,您只需将其初始化即可
for (i = 0; i < sizeof(board)/sizeof(int); i++)
board[0][i] = rand() % 100 + 1;
或者像你一样使用双循环,但是你只需要在另一个循环中循环5次,或者使用sizeof
自动设置迭代次数:
for ( outerLoop = 0 ; outerLoop < sizeof(board)/sizeof(board[0]) ; outerLoop++ )
for ( innerLoop = 0 ; innerLoop < sizeof(board[0])/sizeof(board[0][0]) ; innerLoop++ )
board[outerLoop][innerLoop] = rand() % 100 + 1;
请记住,sizeof
仅在数组的长度在编译时已知时才能以这种方式处理数组,就像在您的示例中一样。
【讨论】:
只有一个条件:没有重复!【参考方案5】:这里有一些伪代码来解决它:
创建一个长度为 100 的“列表”,其中包含数字 1...100,称为“numbersAvailable” 在您的内部循环中设置index = (int)rand() * numbersAvailable;
并获取数字numbersAvailable.get(index);
,然后执行numbersAvailable.remove(index);
在 Java 中创建列表很容易。如果您想坚持使用 C,则必须通过数组来模拟它。 (我可以写下解决方案,但这看起来像一个家庭作业,所以我给你留点东西。
注意:与试验和拒绝解决方案相比,此解决方案的优点是构建结果所需的时间固定。
【讨论】:
【参考方案6】:只需创建大小为 100 的布尔数组:bool numberUsed[100]
。然后在循环中:
1.Generate random number r
2.If numberUsed[r] is true, dont add that r anywhere and continue in loop
3.numberUsed[r] = true
请注意,这种方法需要使用 WHILE 循环,而不是 FOR 循环。
【讨论】:
以上是关于使用循环在数组中生成唯一的随机数的主要内容,如果未能解决你的问题,请参考以下文章