从1到100随机20个不重复的数字出来c++

it2022-05-05  161

//从1到100随机20个不重复的数字出来 //已有下面函数,随机生成一个[min, max]的数 int myRand(int min, int max);

一开始想的是使用set和vector来保存已经随机生成的数,每次要生成新的数的时候,就要通过set来判断是否已经重复。

void Get20RandomNum() { //集合,用来判断数字是否存在,加快查询 set<int> mySet; //vector,用来存储随机数 vector<int> arr(20); //myRand调用次数,防止出现未知bug导致while无法终止 int count = 0; //目前已经获得的不重复的随机数 int num = 0; std::set<int> vals; while (count <= 10000 && num < 20) { int randVal = myRand(0, 100); if (mySet.find(randVal) == mySet.end()) { mySet.insert(randVal); arr[num] = randVal; num++; } count++; } assert(mySet.size() == 20 && arr.size() == 20, "error"); for (auto val : arr) { cout << val << " "; } }

但是这有一个问题,就是具备一个极小的概率,每次新生成的数都是原来的,这样就永远不会得到全部的随机数,因此上面判断count次数是否超过10000,防止while循环永远不会结束,但是这样也没有真正解决问题。

下面使用了另外一种方法进行补充。

codes保存已经生成的随机数,然后myRand生成的范围是剔除了生成的随机数数量后的,例如codes里面有[2]一个数,那么范围应该是100- 1 = 99。每次生成的是偏移量。例如myRand(1, 99)返回2,那么就应该从1开始偏移2,由于2已经生成了,则跳过,为3

int Get1RandowmNum(std::set<int> codes) { //产生从1到剩余区间的偏移 int randVal = myRand(0, 100 - codes.size()); int count = 0; for (int i = 1; i <= 100; i++) { if (codes.count(i) > 0) { continue; } count++; if(randVal == count) { return i; } } return 0; }

这样的复杂度有点大,但是可以作为上面第一个方法的补充,即当循环了10000次仍然不能得到结果的时候,可以选择这个方法进行补充。


最新回复(0)