This solution is random but likely does not give equal probability to all entries. However it avoids having to create new vectors and it is still O(N).
It works by randomly splitting the sequence (in logical sense) in two parts and taking the minimum of each. Then you return the minimum of the two parts.
As I said, it is likely not uniformly distributed but it is indeed still random.
#include <vector>
#include <algorithm>
#include <iostream>
#include <random>
template< typename T >
T minimum( T begin, T end ) {
std::size_t size = std::distance( begin, end );
if ( size<=1 ) return begin;
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<size_t> ds(1,size-1);
auto sep = begin + ds(gen);
auto it1 = std::min_element(begin, sep );
auto it2 = std::min_element(sep, end );
if ( *it1<*it2 ) return it1;
return it2;
}
int main() {
std::vector<int> vec {3, 4, 2, 1, 1, 3, 1};
for ( int j=0; j<10; ++j ) {
auto it = minimum( vec.begin(), vec.end() );
std::cout << *it << " is at a distance of: " << std::distance(vec.begin(), it) << std::endl;
}
return 0;
}
Produces
Program returned: 0
1 is at a distance of: 4
1 is at a distance of: 3
1 is at a distance of: 6
1 is at a distance of: 3
1 is at a distance of: 6
1 is at a distance of: 3
1 is at a distance of: 4
1 is at a distance of: 3
1 is at a distance of: 3
1 is at a distance of: 6
Godbolt: https://godbolt.org/z/3EhzdGndz