random select
problem:
select m number from 0 - (n-1) randomly,
------
solution 1
for each number in 0 - (n-1), in increasing order, generate a random number x, using "(x%remain) < to_select" to decide will the number be choose,
until m number is choosen,
time:
o(n), when n is small, this is quick, but when n is very big, this will be very slow,
------
solution 2
use set to store choosen number, until enough,
time:
o(m*log(m))
space:
o(m)
disadvangate:
when n & m is quite closer, and n is big, this might be slow,
when m is big, will need a lot memory,
------
solution 3
init a n length array in increasing order,
mix the order of first m elements in original array,
then sort the first m elements,
then use the first m elements,
time:
o(n+m*log(m))
space:
o(n)
------
solution 4
base on solution 3,
don't init a n length array, only use a map to store first 5 m elements, and the elements that has been choose for swap with,
time:
o(m*log(m))
space:
o(m)
------
reverse select
if m*2 > n, we can choose to select n-m elements, and exclude them, the remain is m elements,
------
code:
/* @authur kuchaguangjie@gmail.com */
/**
* problem:
select m number from 0 - (n-1) randomly,
*/
#include <stdio.h>
#include <stdlib.h>
/**
* solution 1:
for each number in 0 - (n-1), in increasing order, generate a random number x,
using "(x%remain) < to_select" to decide will the number be choose,until m number is choosen,
* time:
O(n), when n is small, this is quick, but when n is very big, this will be very slow,
*/
void random_m_n(const int m, const int n) {
int remain = n,to_select = m,i=0;
while(to_select>0) {
if(rand()%remain<to_select) {
printf("%d,",i);
to_select--;
}
remain--;
i++;
}
printf("\n");
}
/**
* swap 2 int value,by pointer,
*/
void swap(int *a,int *b) {
int c = *a;
*a = *b;
*b = c;
}
/**
* compare function for int
*/
int int_cmp(int *a,int *b) {
return *a-*b;
}
/**
* solution 2:
init a n length array in increasing order,
mix the order of first m elements in original array,
then sort the first m elements,
then use the first m elements,
* time:
o(n+m*log(m))
* space:
o(n)
*/
void random_m_n_2(const int m, const int n) {
int arr[n],i,swp,x;
for(i=0;i<n;i++) {
arr[i] = i;
}
for(i=0;i<m;i++) {
x = rand()%n;
swap(arr+i,arr+x);
}
qsort(arr,m,4,int_cmp);
for(i=0;i<m;i++) {
printf("%d,",arr[i]);
}
printf("\n");
}
int main(){
random_m_n(30,2000);
random_m_n(0,0);
random_m_n(20,20);
random_m_n_2(30,2000);
random_m_n_2(0,0);
random_m_n_2(20,20);
}
------

本文探讨了从0至n-1范围内随机选取m个数的四种不同算法,并分析了每种算法的时间复杂度和空间复杂度。此外,还提供了一种逆向选择的方法,当m远小于n时使用该方法更加高效。
1083

被折叠的 条评论
为什么被折叠?



