zoukankan      html  css  js  c++  java
  • 随机化算法

    随机化算法(randomized algorithm)

    随机化算法(randomized algorithm)的运行时间不只依赖于特定的输入,而且依赖于所发生的随机数

    对于快排而言,使用随机枢纽元(pivot),将获得 O(NlogN) 的期望时间。

    1. 随机数生成器(generator)

    产生随机数的最简单方法是线性同余数发生器,它于 1951 年由 Lehmer 首先提出。随机数列 xi 的生成满足:

    xi+1=AximodM

    为了开始这个序列,必须给出 x0 某个值,这个值就做种子(seed)。如果 x0=0,那么这个序列永远不是随机的,但是如果 A 和 M 选择得正确,对于任何地 1x<M 都是同等有效的。如果 M 是素数,那么 xi 就绝不会是 0.,比如作如下取值,A=7,M=11,x0=1,那么所产生的随机数为:

    • 7,5,2,3,10,4,6,9,8,1,7,5,2…(循环出现)
    # n 控制随机数的个数
    def randgen(n):
        A, M, x = 7, 11, 1
        for _ in range(n):
            x = x*A % M
            yield x

    如果 M 选择得很大,比如 31 比特(7FFF FFFF)的素数,那么对于大部分的应用来说,周期是非常长的,Lehmer 建议使用 31 个比特的素数 M=2311=2147483647。对于这个素数,A=48271 是给出整周期发生器的许多值中的一个。

    C 程序员来说,在实现时,全局变量用来存放随机数序列的当前值(本文件全局可见)。这个全局变量交由某个程序初始化。当在调试一个使用随机数的程序的时候,最好设置种子(seed,也即 x0)为 1,这使得总是出现相同的随机序列(伪随机序列)。当程序工作时,可以使用系统时钟(时刻都在变化),也可以要求用户输入一个值作为种子。

    static unsigned long Seed = 1;
    #define A 48271 
    #define M 2147483647
    
    double Random() {
        Seed =  (Seed * A) % M;
        return (double) Seed / M;
                // (0, 1)
    }
    
    void Init(unsigned long InitVal) {
        Seed = InitVal;
    }

    对程序中的加法和乘法一定要特别注意,因为这些运算可能会产产生溢出,虽然不会提示错误,但会影响最终的结果,从而影响伪随机性。

    Schrage 给出了一个即使在 32 位机器上执行也不会发生溢出的方案,计算 M/A 的商和余数分别为 Q (quotient)和 R(Remainder)。在 A = 48271,M = 2311 时,Q = 44 488,R = 3399,R < Q,

    则有:

    xi+1===AximodM=AxiMAxiMAxiMxiQ+MxiQMAxiMAxiMxiQ+M(xiQAxiQ)

    等等经历一系列等价替换之后,最终得:

    xi+1=A(ximodQ)RxiQ+Mδ(xi)

    其中 δ(xi) 的值非 0 即 1。仅当余项的值(A(ximodQ)RxiQ)小于 0 时,δ(xi)=1

    static unsigned long Seed = 1;
    #define A 48271
    #define M 2147483647
    #define Q ( M / A )
    #define R ( M % R )
    
    double Random() {
        Seed = A*(Seed % M) - R * (Seed / Q);
        if (Seed < 0)
            Seed += M;
        return (double) Seed / M;
    }
    
    void Init(unsigned long InitVal) {
        Seed = InitVal;
    }
  • 相关阅读:
    lintcode:Flip Bits 将整数A转换为B
    lintcode:strStr 字符串查找
    lintcode:Subtree 子树
    lintcode 容易题:Partition Array by Odd and Even 奇偶分割数组
    lintcode:在二叉查找树中插入节点
    lintcode:在O(1)时间复杂度删除链表节点
    lintcode:哈希函数
    lintcode:合并排序数组 II
    lintcode:合并排序数组
    lintcode:数飞机
  • 原文地址:https://www.cnblogs.com/mtcnn/p/9423358.html
Copyright © 2011-2022 走看看