非重复随机序列生成算法-交换法

【算法3】

“思路2”的基本思想是:利用随机数的生成特点,将已经生成的数值,排除在随机区间之外,这样就可以确保下次生成的随机数一定是新的。具体来说,我们可以这样做:

首先,建立一个长度为N的数组array,初始值是0…N-1。

然后,生成一个随机数x1=random.Next(0, N),则x1∈[0,N)。取num1=array[x1]作为序列中的第一个成员。接下来是关键步骤:将num1和array[N-1]交换。

然后,生成下一个随机数x2= random.Next(0, N-1),则x2∈[0,N-1)。由于num1已经被交换到了array[N-1],而x2<N-1,所以num2=array[x2]一定不等于num1,从而避免了重复。然后将num2和array[N-2]交换。

按照上述方法,可以得到序列中第三、第四…第N个成员。最后得到的array就是一个非重复的随机序列。以下是整个计算过程的图形演示(假设N=5):


C#代码如下:

复制代码
/// <summary>
/// 生成一个非重复的随机序列。
/// </summary>
/// <param name="count">序列长度。</param>
/// <returns>序列。</returns>
private static int[] BuildRandomSequence3(int length) {
    int[] array = new int[length];
    for (int i = 0; i < array.Length; i++) {
        array[i] = i;
    }
    int x = 0, tmp = 0;
    for (int i = array.Length - 1; i > 0; i--) {
        x = random.Next(0, i + 1);
        tmp = array[i];
        array[i] = array[x];
        array[x] = tmp;
    }
    return array;
}
复制代码

经过分析,算法3的时间和空间复杂度都是O(N),性能非常高。通过巧妙的交换位置的方法,可以确保每次得到的数值一定是不重复的,所以不用去判断是否重复。而且,使用数组来保存序列,比List和Hashtable性能更好。

上述算法生成的随机序列是从0到N-1,如果我们指定了别的区间范围呢?例如,要求生成一个非重复的随机序列,范围是[low, high]。实现起来非常简单,只要把算法3稍微改一下就可以了。C#代码如下:

复制代码
/// <summary>
/// 生成一个非重复的随机序列。
/// </summary>
/// <param name="low">序列最小值。</param>
/// <param name="high">序列最大值。</param>
/// <returns>序列。</returns>
private static int[] BuildRandomSequence4(int low, int high) {
    int x = 0, tmp = 0;
    if (low > high) {
        tmp = low;
        low = high;
        high = tmp;
    }
    int[] array = new int[high - low + 1];
    for (int i = low; i <= high; i++) {
        array[i - low] = i;
    }
    for (int i = array.Length - 1; i > 0; i--) {
        x = random.Next(0, i + 1);
        tmp = array[i];
        array[i] = array[x];
        array[x] = tmp;
    }
    return array;
}
复制代码

为了验证上述三种算法的实际性能,我们以生成随机序列所耗的平均时间为标准,进行了实际测试。

测试环境为:Windows7/ CPU 1.6GHZ /VS2008/C#。测试结果为:

序列长度

算法1

算法2

算法3

100

15ms

<1ms

<1ms

1000

46ms

<1ms

<1ms

10000

4430ms

31ms

<1ms

 

 

 

 

 

 

 

【总结】

本文算法3的关键方法是:在现有数组基础上,通过不断地交换位置,来巧妙地达到时间和空间的最优。

其实,一些经典排序算法采用的也是这个思想,例如:冒泡排序、快速排序、堆排序,等等。

算法3也可以理解为一种随机排序算法,可以应用在很多场合,例如:洗牌、抽签等。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值