随机顺序的随机整数

问题描述

       如何生成位于0到n-1之间的k个不同的随机顺序的随机整数?(来源于《编程珠玑》第2版的第1章中第7页习题4)

方法1

  在使用Random类时,每次选择不同的随机因子并在Next中划定范围。这种方法简单容易实现,看上去似乎是可以满足需求的,但我不知道怎么去证明

static void GenRandoInt1(int n , int [] array, int range);
void Main(string[] args){
         int n = 1000000;
         int[] array = new int[n];
         int range = 5000000;
         GenRandomInt1(n, array, range);
         Console.ReadKey();
}

void GenRandomInt1(int n, int[] array, int range){
         Random random;
         for (int i = 0; i < n; i++){
            random = new Random(DateTime.Now.Millisecond + i);
            array[i] = random.Next(0, range);
            random = null;
         }
 }

方法2

使用内置的HashSet容器,在每一次获取范围内随机数时判断容器内是否已经存在有这个随机数,如果存在就重新算一个随机数。

static void GenRandomInt1(int n, int[] array, int range);
static void GenRandomInt2(int n, int range, HashSet<int> hashArray);

void Main(string[] args){
         int n = 1000000;
         int[] array = new int[n];
         int range = 5000000;
            
         HashSet<int> hashArray = new HashSet<int>();
         GenRandomInt1(n, array, range);
         GenRandomInt2(n, range, hashArray);
         Console.ReadKey();
}

void GenRandomInt2(int n, int range, HashSet<int> hashArray){
         Random random = new Random();
         int i = 0;
         for (i = 0; i < n; i++){
           int temp;
           do {
               temp = random.Next(0, range);
              } while (hashArray.Contains<int>(temp));
           hashArray.Add(temp);
         }
}

void GenRandomInt1(int n, int[] array, int range){
          Random random;
          for (int i = 0; i < n; i++){
             random = new Random(DateTime.Now.Millisecond + i);
             array[i] = random.Next(0, range);
             random = null;
          }
}

网上还有一种不用hash的方法,递归判断数组中是否存在已有的随机数,在这里就不多写。

方法3

找一个gcd(n,m)==1的数m,设一个起点x,那么x=(x+m)%n可以将所有的小于n的数遍历,为了产生视觉更加随机的感觉,可以把方程写为x=(x+m*p)%n,p这里是个素数。利用这个公式可以产生等概率而且不重复的k个随机值。

书上答案

for i = [0, n)
    x[i] = i
for i = [0,n)
    swap(i, randint(i, n-1))
    print x[i]

=========================

转载请注明出处http://blog.csdn.net/utimes/article/details/8761541

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值