If k is several thousands and n is tens, then a permutation generation is really not the best choise. But calling getRandNum is not what you want too, because it can return the same value several times.
One option is to generate random sequence all at once, checking that the numbers don't repeat. The easiest (and may be even the most efficient) way to achieve this is to use a set
.
Like so:
#include <vector>
#include <set>
#include <iostream>
#include <random>
class Random
{
public:
Random() : rng( rd() ) { }
inline int getRandNum( int limit ) { return ( numbers(rng) % limit ); }
std::set<int> getRandSequence(int limit, int n);
private:
std::random_device rd;
std::mt19937 rng;
std::uniform_int_distribution<int> numbers;
};
std::set<int> Random::getRandSequence(int limit, int n)
{
std::set<int> generatedSequence;
while (generatedSequence.size() < n) //size() for set is O(1) if I'm not mistaken
generatedSequence.insert(getRandNum(limit));
return generatedSequence;
}
int main()
{
Random r;
auto sequence = r.getRandSequence(1000, 10);
std::cout << "Seq;uence: " << std::endl;
for (int number : sequence)
std::cout << number << std::endl;
std::cout << "End" << std::endl;
return 0;
}
Ideone demo.
By the way, random_device
creation is expensive, but uniform_int_distribution
creation, as far as I remember, is not. So this might be even more efficient:
std::set<int> Random::getRandSequence(int limit, int n)
{
std::uniform_int_distribution<int> uiniformDistribution(0, limit);
std::set<int> generatedSequence;
while (generatedSequence.size() < n)
generatedSequence.insert(uiniformDistribution(rng));
return generatedSequence;
}
Besides, when you get a uniform distribution and then apply % limit
to it, you don't get a uniform distribution anymore.