产生不重复的随机数

来源:互联网 发布:钢铁侠玩具模型淘宝 编辑:程序博客网 时间:2024/04/28 23:29
看到这个问题了:
随机取 m 个数(在 1 到 n 的范围之内),(m <= n),要求 m 个数没有重复。
有没有什么好的算法,时间复杂度和空间复杂度都很好。


// 随机取 m 个数(在 1 到 n 的范围之内),(m <= n),要求 m 个数没有重复。
// 有没有什么好的算法,时间复杂度和空间复杂度都很好。
// 方法 1 :生成一系列的随机数,重复的丢弃,利用 STL 的 set 可以方便地插入非重复元素。
// 缺点是浪费时间。
// 方法 2 :洗牌算法,用一个数组保存 1,2, 。。。,n 这些数,然后历遍数组,每次生成一个
// 随机数,作为下标,交换当前元素。然后取数组的前 m 个元素。缺点是浪费空间。
// 2007-07-23
// By rappizit@yahoo.com.cn

#include 
<iostream>
#include 
<set>
#include 
<vector>
#include 
<stdlib.h>
#include 
<time.h>
using namespace std;

void randomNexclusive(int n, int m)
{
    
if (n < m)
        
{
        
return;
        }

    
int r;
    
set <int> s;
    
while (1)
        
{
        r 
= rand () % n + 1;
        s.insert (r);    
// set 底层实现是红黑树,插入复杂度是对数级的
        if(s.size () == m)
            
{
            
break;
            }

        }

    copy (s.begin (), s.end (), ostream_iterator 
<int> (cout, " "));
    cout 
<< endl;
}


void shuffle (int n, int m)
{
    
if (n < m)
        
{
        
return;
        }

    vector 
<int> v (n + 1);
    
int r, i;
    
for (i = 1; i <= n; i ++)
        
{
        v [i] 
= i;
        }

    
for (i = 1; i <= n; i ++)
        
{
        r 
= rand () % n + 1;
        swap (v [i], v [r]);
        }

    
for (i = 1; i <= m; i++)
        
{
        cout 
<< v [i] << " ";
        }

    cout 
<< endl;
}


void main ()
{    // 此句必不可少,否则生成相同序列,放到函数 randomNexclusive () 里面也不好
    srand ((unsigned) time (NULL));    
    randomNexclusive (
1000100);
    cout 
<< endl;
    shuffle (
1000100);
}

不过我认为这两个算法都还是能够满足一般要求的。
原创粉丝点击