精华内容
下载资源
问答
  • 随机算法-蒙特卡罗算法
    千次阅读
    2020-06-30 13:57:53

    在论文中多次看到ε-approximation概念,然后百度发现也很少说这个的。只有在其他论文里面有讲到。这里就是记录下目前所了解的比较浅显的理解。

    可以比较论文基于k-means的(1+ε)近似算法求解,(对比k-means和ε-approximation 有类似之处)其中有一段说到:
    利用随机算法技术,通过随机选取一些点集合,保证以一定概率求出近似于(1+ε)值的最优解,其中ε为一任意小的常数。根据蒙特卡洛(Monte Carlo)算法原理,通过多次运行该算法可求出其近似于(1+ε)值的最优解。

    那么我们可以理解为,随机选取一些离散点集合,保证以一定的概率求出近似于ε值的最优解,(高等数学中求近似解,往往是极限时,ε为任意小的常数且不为0)。

    这里提到了根据蒙特卡罗算法原理,算法经过多次运行可以得到近似于ε的最优解。

     

    蒙特卡罗算法

    蒙特卡罗Monte Carlo 又称随机抽样或统计试验方法,是以概率和统计理论方法为基础的一种计算法方法。使用随机数或者伪随机数来解决很多计算问题的方法,将所求解的问题同一定的概率模型相联系,用电子计算机实现统计模拟或抽样,以获得问题的近似解。

    蒙特卡罗解题归结为三个主要步骤:

    • 构造或描述概率过程;
    • 实现从已知概率分布抽样;
    • 建立各种估计量

    借助计算技术,蒙特卡罗模拟实现了两大优点:

    • 简单,省却了繁复的数学报导和演算过程,使得一般人也能够理解和掌握;
    • 快速,简单和快速是蒙特卡罗方法在现代项目中获得应用的基础。

     

    更多相关内容
  • 红包随机算法实现

    2018-08-15 20:38:54
    1.基于Java实现的红包随机分配算法, 2.先抢后抢拿到红包的大小的期望是大致相等的
  • 随机算法

    千次阅读 2018-05-17 08:35:26
    概述 随机算法是一种在接受输入的同时,为了随机选择的目的,还接受一串随机比特流并且在运行过程中使用该比特流的算法(允许算法在执行过程中随机地...随机算法的基本特征:对所求解问题的同一实例用同一随机算法...

    概述

    随机算法是一种在接受输入的同时,为了随机选择的目的,还接受一串随机比特流并且在运行过程中使用该比特流的算法(允许算法在执行过程中随机地选择下一个计算步骤)。

    随机算法通常有两个优点

    • 较之那些我们所知的解决同一问题最好的确定性算法,随机算法所需的运行时间或空间通常小一些。
    • 随机算法比较易于理解和实现(呵,站着说话不腰疼)。

    随机算法的基本特征:对所求解问题的同一实例用同一随机算法求解两次可能得到完全不同的效果。
    这两次求解所需的时间、所得到的结果可能会有相当大的差别。

    随机算法的类别

    随机(概率)算法大致分四类:

    • 数值概率算法

      常用于数值问题的求解。
      这类算法所得到的往往是近似解且近似解的精度随计算时间的增加而不断提高。
      在许多情况下,要计算出问题的精确解是不可能的,或者没有必要,此时,用数值概率算法可以得到相当满意的解。

    • 蒙特卡洛(Monte Carlo)算法

      用于求问题的准确解。
      对于许多问题来说,近似解毫无意义。
      例如,一个判定问题其解为“是”或“否” ,二者必居其一,
      不存在任何近似解。
      又如,我们要求一个整数的因子,这样问题的解答必须是准
      确的,一个整数的近似因子没有任何意义。
      用蒙特卡洛算法能求得问题的一个解,但这个解未必是正确的。
      求得正确解的概率依赖于算法所用的时间,算法所用的时间越多,得到正确解的概率就越高。
      蒙特卡洛算法的主要缺点也在于此,即无法有效地判定所得到的解是否肯定正确。

    • 拉斯维加斯(Las Vegas)算法

    拉斯维加斯算法不会得到不正确的解。
    一旦用拉斯维加斯算法找到一个解,这个解就一定是正确
    解。
    但有时用拉斯维加斯算法会找不到解。
    与蒙特卡洛算法类似,拉斯维加斯算法找到正确解的**概率随着它所用的计算时间
    的增加而提高**。
    对于所求解问题的任一实例,用拉斯维加斯算法反复对该实例求解足够多次,可使求解失效的概率任意小。

    • 舍伍德(Sherwood)算法

    舍伍德算法总能求得问题的一个解,且所求得的解总是正确的。
    当一个确定性算法在最坏情况下的计算复杂性与其在平均情况下的计算复杂性有较大差别时,可在这个确定性算法中引入随机性,将它改造成一个舍伍德算法,消除或减少问题的好坏实例间的这种差别。

    例子


    • Monte Carlo算法

    总是给出解,但是偶尔可能会产生非正确的解。然而,可以通过多次运行原算法,并且满足每次运行时的随机选择都相互独立,使产生非正确解的概率可以减到任意小。

    主主元素问题(多数元素问题)

    问题描述

    设T[1…n]是一个长度为n的数组,当某个元素在该数组中存在的数量多于int(s/2)时称该元素为数组T的主元素(多数元素)。

    求解思路

    算法随机选择数组元素x,由于数组T的非主元素个数小于n/2,所以,x不为主元素的概率小于1/2。因此判定数组T的主元素存在性的算法是一个偏真1/2正确的算法。50%的错误概率是不可容忍的,利用重复调用技术将错误概率降低到任何可接受的范围内。对于任何给定的p> 0,算法majorityMC重复调用(向上取整)log(1/p)次算法majority。它是一个偏真蒙特卡罗算法,且其错误概率小于p。算法majorityMC所需的计算时间显然是O(nlog(1/p))。

    代码实现

    //重复k次调用算法Majority
    template<class Type>
    bool MajorityMC(Type *T,int n,double e)
    {
        int k = ceil(log(1/e)/log((float)2));
        for(int i=1; i<=k; i  )
        {
            if(Majority(T,n))
            {
                return true;
            }
        }
        return false;
    }
    
    
    bool Majority(Type *T,int n)
    {
        RandomNumber rnd;
        int i = rnd.Random(n);
    
        Type x = T[i];  //随机选择数组元素
        int k = 0;
    
        for(int j=0; j<n; j  )
        {
            if(T[j] == x)
            {
                k  ;
            }
        }
    
        return (k>n/2); //k>n/2时,T含有主元素
    }
    

    随机化快速排序

    (可能是最为流行的一种随机算法?)
    首先要明确传统快速排序的流程:从待排序序列中拿出最后一个(或者第一个)作为主元,将小于它的放在它的前面,大于它的放在它的后面,这时对该主元的前一部分和后一部分再分别递归进行“划分”,最后达到有序。这种方法有一个很大的问题就是当待排序数组是一个几乎有序的序列时其复杂度会很容易达到senta(n^2),因为如果每次都选择第一个元素或者最后一个元素作为主元进行划分,对一个几乎有序的序列,划分后的递归对象(子序列)将会一个很长一个很短,这样可能经过好多次划分后还是有一个待划分的子部分很长。解决方法是每次不选择第一个或者最后一个作为主元,而是随机产生一个从第一个到最后一个之间的随机数作为主元进行划分,这样即保留了快速排序的优越性又避免了排序几乎有序序列时的痛点。

    核心代码

    void RandomQuickSort(int low,int high){
        if(low<high){
    
            int v=random(low,high);
            int t=A[low];
            A[low]=A[v];
            A[v]=t;
    
            Split(A[low...high],low);
            RandomQuickSort(low,v-1);
            RandomQuickSort(v 1,high);
        }
    }
    

    该算法在最坏情况下仍然是senta(n^2),但这与输入形式无关。如果最坏情况发生,那是因为用随机数选取的主元不凑巧,这个事件发生的概率是非常小的。事实上,没有一种输入的排列可以引起它的最坏情况,算法的期望运行时间是senta(nlogn).

    随机化的选择算法

    什么是选择算法:

    SELECT 算法描述

    1. 如果数组元素个数小于 44,则直接将数组排序并返回第 k小元素(采用直接的方法来解决问题,因为当总元素个数小于44*5=220的时候用直接的方法解决问题更快)。
    2. 把 n 个元素以每组 5 个元素划分为 int( n/5) 组,如果 n 不是 5的倍数则抛弃剩余元素。
    3. 对每组进行排序,之后取出每组的中间项(第 3 个元素)。
    4. 递归调用 SELECT 算法,得到这些中间项序列中的中项元素 mm
    5. 根据 mm,将原数组 A 划分为三个子数组:

      • A1={小于 mm 的元素};
      • A2={等于 mm 的元素};
      • A3={大于 mm 的元素};
    6. 根据 k 的大小,判断第 k 小元素会出现在 A1,A2,A3 中的
      哪一个数组里,之后,或者返回第 k 小元素(mm,在 A2
      中),或者在 A1 或 A3 上递归。

      1:k <len(A 1) 第 k 小元素在 A1 中;
      2:len(A 1) =k <= A 1  A 2 第 k 小元素在 A2 中;
      3: A 1   A 2 < k <= A 1   A 2   A 3第 k 小元素在 A3 中;
      

      该算法的运行时间是senta(n)(T(n)<=20cn,c是排序43个元素所需的时间),具有一个很大的常数系数,所以就有了随机版的选择算法:

      /*
       * 输入:n个元素的数组A[1...n]和整数k
       * 输出:A中的第k小元素
       * 
       */
      
      R_Select(A,1,n,k);
      
      void R_Select(int *A, int low, int high, int k) {
          int v = random(low, high);
          int x = A[v];
          A1 = {a | a < x};
          A2 = {a | a = x};
          A3 = {a | a > x};
      
          if (A1.len >= k)return R_Select(A, 1, A1.len, k);
          else if (A.len   A2.len >= k)return x;
          else if (A1.len   A2.len < k)return R_Select(A, 1, A3.len, k - A1.len - A2.len);
      }
      

    该版本的随机算法与原版本的主要不用是原版本是将序列分为若干个5元素序列分别进行排序后找到那些5元素序列中值组成的新序列的中值作为主元对元素进行划分,而随机算法是产生一个序列中的随机数(就是在待找序列中随机找了一个数)作为主元,省去了那些排序5元素数组的步骤,对于大小为n的输入,算法RandomizedSekect执行的期望比较次数小于4n,他的期望运行时间是senta(n)。
    可以发现该随机算法最坏情况下的运行时间也是senta(n),但是其发生最坏情况不依赖于输入,仅当产生的随机数序列很不凑巧时才会发生,而这种概率是非常小的。

    展开全文
  • 红包随机算法&微信群红包随机算法

    千次阅读 2021-02-20 11:14:40
    1.前言 因疫情影响,部门 2021 年会以线上直播的形式进行,通过微信小程序展开。为活跃年会氛围,年会直播间会有抢红包环节。因产品要求,红包金额...所以这里可以抽象成如下算法: input: <sum, num, min, max>

    在这里插入图片描述

    1.前言

    因疫情影响,部门 2021 年会以线上直播的形式进行,通过微信小程序展开。为活跃年会氛围,年会直播间会有抢红包环节。因产品要求,红包金额要随机生成,所以这里涉及到指定红包总额、数量和最大最小值情况下如何生成红包金额。

    可以看出,红包随机金额生成的输入是一个四元组 <sum, num, min, max>,其中 sum 是红包总额,num 是红包数量,min 和 max 分别是红包最小最大值。所以这里可以抽象成如下算法:

    input: <sum, num, min, max>
    output: 随机红包金额数组
    

    因为法币都有最小单位,比如人民币是分,所以上面输入四元组均可视为整数。

    2.参考微信群红包算法

    本质上,这和微信群红包没什么区别,发出一个固定总金额的红包,指定红包数量,那么随机分配红包金额时需要满足哪些规则?
    (1)所有人抢到金额之和等于红包总金额,不能超过,也不能少于;
    (2)抢到的红包金额至少是一分钱;
    (3)要保证抢到红包的人获取到的红包金额是随机的。

    实际上,微信群红包的 min 是 1 分钱,max 是剩余红包金额均值的两倍,为什么是这两个值,因为这么做会保证随机值的期望值等于均值,来保证不会因为抢红包的先后顺序而造成不公平。这两个值是算法内设的,不提供给用户指定。另外总金额 sum 和数量 num 是由用户指定的。

    为什么微信群红包要搞一个最大上限,因为如果不设置一个最大上限,会出现一种不公平的现象。就是越在前边领取红包的同学,其可随机范围越大,获得大额红包的几率也越高。一旦前边的同学随机到一个较大的金额,后边的同学可以随机的范围就逐步收窄,抢红包就变成了一个拼手速的游戏了。

    实际上,微信群红包采用的是二倍均值法,也就是每次随机上限为剩余红包金额均值的两倍

    微信群红包金额分配算法是这样的:

    每次抢红包直接随机,随机的范围是[1, 剩余红包金额均值的两倍],单位分
    

    这个公式,保证了每次随机金额的平均值是相等的,不会因为抢红包的先后顺序而造成不公平。

    实际上微信群红包的算法虽然公平,但是有个缺陷,不过这个微信产品同学可以接受,只是对于用户来说体验并不是那么友好,因为有时发个群红包会出现下面这种最后两个之一红包金额非常大的情况。

    出现这种情况的原因是,上面的随机上限 max 为剩余红包金额均值的两倍,如果剩余红包金额均值越来越大,那么越是后抢期望越大,就会出现上面这种情况。当然,出现这种情况的概率非常小,需要除了最后两次之前的所有结果都小于剩余均值,即小金额。

    这说明了一个什么问题呢?红包金额随机分配算法不是一个标准算法,而是产品逻辑。 如果你是产品同学,你完全可以搞一个你想要的随机分配算法,比如随机范围严格在 [min, max] 之间,或者像微信群红包那样,每次抢红包时,max 是动态变化的。

    这里说下大家最关心的问题,就是如何才能抢到大红包。通过上面的介绍,结论就是除了最后两个红包金额之一有可能很大,因为每次都是在 [0.01 - 剩余均值*2] 之间随机,越往后剩余均值可能越大,导致最后两位抢时,期望最大。如果红包数量充足,那么最后两位抢才有可能获得大红包。但绝大部分情况是僧多粥少,需要拼手速才能抢到红包,这种情况下,你不能保证你是最后两位抢到红包的人。

    3.一个可用的随机算法

    此次年会产品同学开始跟我说需要像微信群红包那样的随机分配红包金额,但是仔细研究了微信群红包的算法,才发现产品同学想要的效果和微信群红包并不同,她想要的是红包金额严格随机范围在 [min, max]。

    在实现时要满足如下几个条件:
    (1)所有人抢到金额之和等于红包总金额,不能超过,也不能少于;
    (2)抢到的红包金额在 [min, max] 之间;
    (3)要保证抢到红包的人获取到的红包金额是随机的。

    下面给一个可行的随机分配算法。

    // min 最小金额分 max 最大金额分 num 红包数量 sum 红包总额分
    input:<min, max, num, sum>
    
    // 参数合法性校验
    step 1: min*num <= sum <= max*num 
    step 2: 将 num 个在 min 填入数组
    step 3: 循环随机一个范围为 [0, max - min] 数加到最小值数组中。如果随机数大于剩余金额,则取剩余金额作为随机数;如果累加值大于最大值,则取最大值与原值差值作为随机数。如果剩余金额为 0 结束循环
    step 4: 如果均值靠近 min 或 max,第三步分别会出现很多 min 或者 max,看起来不够随机。这里需要经过一轮或多轮遍历,将 (min, max) 之间的数减掉部分给到 min 或者从 max 获得部分
    step 5: 打乱数组顺序
    

    注意,在第四步消除最小值或最大值,是控制在一定比例还是完全消除,也是一个产品逻辑,需要由产品同学来定。下面的实现示例,只进行一轮循环,可能会存在少量最小值或最大值。

    下面以 NodeJS 为例,给出实现。

    // brief: 获取随机整数 [min, max]
    function random(min, max) {
      const range = max - min;
      const rand = Math.round(Math.random() * range);
      return min + rand;
    }
    
    // brief: 消除最小值和最大值
    function smooth(min, max, arr) {
      for (let i = 0; i < arr.length; i++) {
        if (!(min < arr[i] && arr[i] < max)) {
          continue
        }
        for (let j = 0; j < arr.length; j++) {
            // 消除最小值
            if (arr[j] === min) {
              let rm = Math.floor((arr[i] - min)/10)
              arr[i] -= rm
              arr[j] += rm
              break
            }
            // 消除最大值
            if (arr[j] === max) {
              let rm = Math.floor((max - arr[i])/10)
              arr[i] += rm
              arr[j] -= rm
              break
            }
        }
      }
    }
    
    // brief: 打乱数组顺序
    function shuffle(arr) {
      arr.sort(() => Math.random() - 0.5);
    }
    
    // brief: 生成随机整数数组
    function randnum(min, max, num, sum) {
      // step 1 检查参数
      if (min <= 0 || max <= 0 || num <= 0 || sum <= 0) {
        return [];
      }
      if (!(min * num <= sum && sum <= max * num)) {
        return [];
      }
    
      // step 2 将 num 个在 min 填入数组
      var arr = new Array(num).fill(min);
      
      // step 3 循环随机生成[0, max-min]加到最小值数组
      let leftTotal = parseInt(sum - min*num);
      LABEL:
      while(true) {
        for (let i = 0; i < num; i++) {
            let rand = random(0, parseInt(max-min));
            // 如果随机数大于剩余金额,则取剩余金额作为随机数
            if (rand > leftTotal) {
                rand = leftTotal;
            }
            // 如果累加值大于最大值,则取最大值与原值差值作为随机数
            if (arr[i] + rand > max) {
                rand = max - arr[i];
            }
            arr[i] += rand;
            leftTotal -= rand;
            if (leftTotal === 0) {
                break LABEL;
            }
        }
      }
      
      // step 4 消除大部分最小值和最大值
      smooth(min, max, arr)
      
      // step 5 打乱数组顺序
      shuffle(arr)
      
      return arr;
    }
    

    上面的代码可以在 Online NodeJS IDE 执行。

    下面采用两组入参,均值分别靠近最小值和最大值来观察多次运行后的输出结果。

    第一组入参,最小金额 5 元,最大金额 50 元,数量 10 个,总金额 100 元。均值 10 靠近最小值。

    // 单位为分
    console.log(randnum(500, 5000, 10, 10000))
    
    // 第一轮结果
    [ 516, 3317, 646, 515,  677, 636, 1861,  501, 518, 813 ]
    
    // 第二轮结果
    [ 724,  502,  500, 726, 2761, 2740, 500,  502,  522, 523 ]
    
    // 第三轮结果
    [ 500, 500, 1009, 899, 504, 4492, 500, 505,  551, 540 ]
    

    第二组入参,均值靠近最大值,最小金额 5 元,最大金额 50 元,数量 10 个,总金额 450 元。均值 45 靠近最大值。

    // 单位为分
    console.log(randnum(500, 5000, 10, 40000))
    
    // 第一轮结果
    [ 4832, 4999, 4953, 4990, 3515, 3929, 4835, 4572, 3482, 4893 ]
    
    // 第二轮结果
    [ 4868, 5000, 4901, 5000, 4733, 5000, 4106, 3804, 2588, 5000 ]
    
    // 第三轮结果
    [ 4999, 3493, 3795, 5000, 3210, 4849, 4867, 4985, 5000, 4802 ]
    

    从上面的实验结果可以看出,相同入参多次运行结果是不同的。如果均值靠近最小值或者最大值,结果可能分别会出现多个最小值和最大值,这个可以通过多次执行 smooth 函数来完全消除。


    参考文献

    [1] 漫画:如何实现抢红包算法?
    [2] 微信拼手气红包背后的算法逻辑

    展开全文
  • java随机算法

    千次阅读 2018-02-23 11:28:27
    在日常工作中,经常需要使用随机算法。比如面对大量的数据, 需要从其中随机选取一些数据来做分析。 又如在得到某个分数后, 为了增加随机性, 需要在该分数的基础上, 添加一个扰动, 并使该扰动服从特定的概率分布...

    在日常工作中,经常需要使用随机算法。比如面对大量的数据, 需要从其中随机选取一些数据来做分析。 又如在得到某个分数后, 为了增加随机性, 需要在该分数的基础上, 添加一个扰动, 并使该扰动服从特定的概率分布。本文主要从这两个方面出发, 介绍一些算法, 供大家参考。

    首先假设我们有一个使用的随机函数float frand(), 返回值在(0, 1)上均匀分布。大多数的程序语言库提供这样的函数。 在其他的语言如C/C++中, 可以通过间接方法得到。如 frand()= ((float)rand() ) / RAND_MAX;

    1, 随机选取数据

    假设我们有一个集合A(a_1,…,a_n), 对于数m,0≤m≤n, 如何从集合A中等概率地选取m个元素呢?
    通过计算古典概率公式可以得到, 每个元素被选取的概率为m/n。 如果集合A里面的元素本来就具有随机性, 每个元素在各个位置上出现的概率相等, 并且只在A上选取一次数据,那么直接返回A的前面m个元素就可以了, 或者可以采取每隔k个元素取一个等类似的方法。这样的算法局限很大, 对集合A的要求很高, 因此下面介绍两种其他的算法。

    1.1 假设集合A中的元素在各个位置上不具有随机性, 比如已经按某种方式排序了,那么我们可以遍历集合A中的每一个元素a_i, 0<=n 根据一定的概率选取ai。如何选择这个概率呢?

    设m’为还需要从A中选取的元素个数, n’为元素a_i及其右边的元素个数, 也即n’=(n-i+1)。那么选取元素a_i的概率为 m’/n’。
    由于该算法的证明比较繁琐, 这里就不再证明。
    我们简单计算一下前面两个元素(2<=m<=n)各被选中的概率。
    1) 设p(a_i=1)表示a_i被选中的概率。显而易见, p(a_1=1)=m/n, p(a_1=0)为(n-m)/n;
    2)第二个元素被选中的概率为
    p(a_2=1)= p(a_2=1,a_1=1)+p(a_2=1,a_1=0)
    = p(a_1=1)*p(a_2=1│a_1=1)+ p(a_1=0)* p(a_2=1│a_1=0)
    = m/n * (m-1)/(n-1) + (n-m)/n*m/(n-1)
    = m/n

    我们用c++语言, 实现了上述算法

    template<class T>
    bool getRand(const vector vecData, int m, vector& vecRand)
    {
            int32_t nSize = vecData.size();
        if(nSize  < m || m < 0)
            return false;
        vecRand.clear();
            vecRand.reserve(m);
        for(int32_t i = 0, isize = nSize; i < isize ; i++){
                float fRand = frand();
                if(fRand <=(float)(m)/nSize){
                    vecRand.push_back(vecData[i]);
                    m--;
                }
            nSize --;
        }
        return true;
    }

    利用上述算法, 在m=4, n=10, 选取100w次的情况下, 统计了每个位置的数被选取的概率

    位置 概率
    1 0.399912
    2 0.400493
    3 0.401032
    4 0.399447
    5 0.399596
    6 0.39975
    7 0.4
    8 0.399221
    9 0.400353
    10 0.400196
    还有很多其他算法可以实现这个功能。比如对第i个数, 随机的从a_i, …, a_n中, 取一个数和a_i交换。这样就不单独介绍了。

    1.2 在有些情况下,我们不能直接得到A的元素个数。比如我们需要从一个很大的数据文件中随机选取几条数据出来。在内存不充足的情况下,为了知道我们文件中数据的个数, 我们需要先遍历整个文件,然后再遍历一次文件利用上述的算法随机的选取m个元素。

    又或者在类似hadoop的reduce方法中, 我们只能得到数据的迭代器。我们不能多次遍历集合, 只能将元素存放在内存中。 在这些情况下, 如果数据文件很大, 那么算法的速度会受到很大的影响, 而且对reduce机器的配置也有依赖。

    这个时候,我们可以尝试一种只遍历一次集合的算法。
    1)   取前m个元素放在集合A’中。
    2)   对于第i个元素(i>m), 使i在 m/i的概率下, 等概率随机替换A’中的任意一个元素。直到遍历完集合。
    3)   返回A’

    下面证明在该算法中,每一个元素被选择的概率为m/n.
    1)   当遍历到到m+1个元素时, 该元素被保存在A’中的概率为 m/(m+1), 前面m个元素被保存在A’中的概率为 1- (m/m+1 * 1/m) = m/m+1
    2)   当遍历到第i个元素时,设前面i-1个元素被保存在A’中的概率为 m/(i-1)。根据算法, 第i个元素被保存在A’中的概率为m/i , 前面i-1各个元素留在A’中的概率为 m/(i-1) * (1-(m/i* 1/m) = m/i;
    3)   通过归纳,即可得到每个元素留在A’中的概率为 m/n;

    我们在类似 hadoop的reduce函数中, 用java实现该算法。

    public void reduce(TextPair key, Iterator value, OutputCollector collector, int m)
    {
        Text[] vecData = new Text[m];
        int nCurrentIndex = 0;
        while(value.hasNext()){
            Text tValue = value.next();
            if(nCurrentIndex < m){
               vecData[nCurrentIndex] = tValue;
            }
            else if(frand() < (float)m / (nCurrentIndex+1)) {
               int nReplaceIndex = (int)(frand() * m);
               vecData[nReplaceIndex] = tValue;
            }
            nCurrentIndex ++;
        }
     //collect data
    …….
    }

    利用上述算法,在m=4, n=10, 经过100w次选取之后, 计算了每个位置被选择的选择的概率

    位置 概率
    1 0.400387
    2 0.400161
    3 0.399605
    4 0.399716
    5 0.400012
    6 0.39985
    7 0.399821
    8 0.400871
    9 0.400169
    10 0.399408

    2. 随机数的计算

    在搜索排序中,有些时候我们需要给每个搜索文档的得分添加一个随机扰动, 并且让该扰动符合某种概率分布。假设我们有一个概率密度函数f(x), min<=x<=max, 并且有
    随机算法
    那么可以利用f(x)和frand设计一个随机计算器r(frand()), 使得r(frand())返回的数据分布, 符合概率密度函数f(x)。

    随机算法
    那么函数
    随机算法
    符合密度函数为f(x)的分布。
    下面对这个以上的公式进行简单的证明:

    由于g(x)是单调函数, 并且x在[0,1]上均匀分布,那么

    随机算法
    由于上述公式太复杂, 计算运算量大, 在线上实时计算的时候通常采用线性差值的方法。
    算法为:
    1)在offline计算的时候, 设有数组double A[N+1];对于所有的i, 0<=i<=N, 令
    随机算法
    2)在线上实时计算的时候,
    令f = frand(),
    lindex = (int) (f* N);
    rindex = lindex +1;
    那么线性插值的结果为 A[lindex]*(A[rindex]-f) + A[rindex] * (f – A[lindex])
    我们做了一组实验,令f(x)服从标准正太分布N(0,1), N=10000, 并利用该算法取得了200*N个数。对这些数做了个简单的统计, 得到x轴上每个小区间的概率分布图。

    随机算法
    3后记
    在日常工作中, 还有其他一些有趣的算法。比如对于top 100w的query, 每个query出现的频率不一样, 需要从这100w个query, 按照频率越高, 概率越高的方式随机选择query。

    展开全文
  • 随机算法(中文版)

    2013-04-02 17:40:41
    本资源主要讲述了随机算法的知识,想了解随机算法的话还是不错的。
  • 随机算法(上)

    千次阅读 2017-10-30 15:43:14
    随机算法(上)
  • 第七章 随机算法及NP完全问题 ;7.1 随机算法引言;8.1 随机算法引言;7.2 随机算法的类型 ;7.2 随机算法的类型;7.2 随机算法的类型;7.3 随机数发生器 ;7.3 随机数发生器;7.4 数值概率算法;7.4 数值概率算法;7.5 舍伍德...
  • LeetCode-【随机算法】解题技巧

    千次阅读 2022-02-19 20:49:25
    384. 打乱数组 class Solution: def __init__(self, nums: List[int]): self.data = nums[:] self.curr = nums self.len = len(nums) def reset(self) ->... self.curr = self.data[:] ...
  • 权重随机算法

    千次阅读 2018-10-30 17:38:37
    GetDatas方法可以获取到当前这一次随机的值。 思路就是将权重值乘一个1到100的随机数,然后将随机后的权重值排序。 [code]csharpcode: using System.Collections; using System.Collections.Generic;...
  • 几种随机算法的实现原理

    万次阅读 2016-10-23 15:31:04
    在日常工作中,经常需要使用随机算法。比如面对大量的数据, 需要从其中随机选取一些数据来做分析。 又如在得到某个分数后, 为了增加随机性, 需要在该分数的基础上, 添加一个扰动, 并使该扰动服从特定的概率...
  • code小生一个专注大前端领域的技术平台公众号回复Android加入安卓技术群“本文内容编写时,参考了网上的资料,详见“参考资料”部分,感谢分享者。。本文已同步发布于52im社区:h...
  • 素数测试随机算法

    千次阅读 2017-10-30 22:16:24
    素数测试随机算法
  • 游戏中常用的伪随机算法之PRD暴击算法

    千次阅读 多人点赞 2020-09-03 20:29:04
    游戏中常用的伪随机算法之PRD暴击算法 PRD伪随机算法常用于游戏中的暴击算法,因此本文的标题将其称为 PRD暴击算法。 诞生与应用 PRD算法诞生与《魔兽争霸3》,可以说其诞生就是为了解决游戏中暴击概率所存在的问题...
  • 带权重的随机算法的快速实现

    千次阅读 2018-02-08 11:44:10
  • 前言在产品需求中,比如抽奖,配对,会用到随机的概念 ,对应到功能实现中,也就是对应的随机算法。单随机需求比如做一个简单的抽奖轮盘,每次抽奖,随机出一个结果,由前端展示抽奖结果。每个奖项都有对应的中奖...
  • 笔记来源:高级算法设计(孙晓明...随机算法在近似算法中的应用 本节问题可能利用条件期望去随机化,将随机化算法转化为近似算法,也可以利用LP+rounding+ 条件期望去随机化 1. MAX-SAT定义 SAT,NP问题是否存在...
  • 一个简单的随机算法——红包算法

    千次阅读 2019-01-02 18:11:42
    一个简单的红包生成算法,代码如下: /** * 红包 * @param n * @param money 单位:分 * @return */ public static double[] redPacket(int n, double money) { // 红包结果 double[] result = new double...
  • 带权重的随机算法

    万次阅读 2016-10-04 14:26:21
    在软件开发过程中,尤其是APP或者或者游戏中,经常会涉及到这样一种问题:为了刺激用户消费,需要设置一种抽奖功能,用户点击抽奖按钮,会随机获取其中一种奖励,但是问题来了,不能让一等奖太容易抽到,那样的话,...
  • 随机算法之随机选择

    千次阅读 2017-10-30 20:02:23
    随机算法之随机选择
  • 随机均衡分配,抽奖的一个随机算法

    千次阅读 2017-12-17 23:47:19
    最近在写一个随机的均衡的一个抽奖的算法,要保证不能连续抽中, 要均衡一点,不能超过指定的中奖数,当然也不能小于,必须是这个中奖数字, 下面是我写的一个,, 0表示不中,1表示中,就这样生成一串奖池.. 个人...
  • 使用随机算法产生一个数,要求把1-1000W之间这些数全部生成。(考察高效率,解决产生冲突的问题) 代码虽然实现了。 提高效率的地方有如下: 1.初始化set集合的时候 Sets.newHashSetWithExpectedSize(value), 给...
  • java实现微信红包随机算法

    千次阅读 2017-01-23 13:41:49
    * 分红包核心算法 * @param money * @param minS * @param maxS * @param count * @return */ public float randomRedPacket(float money,float minS,float maxS,int count) { //当人数剩余一个时,把当前...
  • 红包随机分配算法

    2017-05-12 14:31:38
    红包随机分配算法
  • 随机算法之最小割问题

    千次阅读 2017-10-31 10:42:20
    随机算法之最小割问题
  • 【算法】3 由招聘问题看随机算法

    千次阅读 热门讨论 2015-05-29 22:22:00
    某天,你想雇用一名算法工程师。当然,不可能让你这个Boss亲自去到处练习应聘者,而是选择了中介。雇用中介每天都会给你推荐一个应聘者(PS:还是让自己轻松点,一天只应聘一个人哈)。是个地球人都知道,你必须要给...
  • 随机算法全面总结

    万次阅读 2012-08-29 16:21:27
    随机算法涉及大量概率论知识,有时候难得去仔细看推导过程,当然能够完全了解推导的过程自然是有好处的,如果不了解推导过程,至少记住结论也是必要的。本文总结最常见的一些随机算法的题目,也当作面试的准备工作吧...
  • 【记录学习笔记,方便自己理解。 】 ... 以100为例,1000W时将value值更改即可,选取1-100范围方便时输出检验是否正确。 先构建一个value大小的数组,按...有了这样一个数组之后,用random.nextInt(value) 每次随机...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 701,518
精华内容 280,607
关键字:

随机算法

友情链接: 音乐播放器.rar