zoukankan      html  css  js  c++  java
  • 随机洗牌

    问题:给定一个有序序列1~n,要你将其完全打乱,要求每个元素在任何一个位置出现的概率均为1/n。

    解决方案:依次遍历数组,对第n个元素,以1/n的概率与前n个元素中的某个元素互换位置,最后生成的序列即满足要求,1/n的概率可通过rand() % n实现。见如下程序:

    void swap(int* p, int* q)

    {

        int tmp = *p;

        *p = *q;

        *q = tmp;

    }

     

    void shuffle(int *arr, int n)

    {

        int i;

        for(i = 0; i < n; i++) {

            int idx = rand() % (i + 1); //选取互换的位置

            swap(&arr[idx], &arr[i]);

        }

    }

     

     使用数学归纳法证明:

    l  当n=1时,idx必为0,所以元素arr[0]在任何一个位置的概率为1/1,命题成立。

    l  假设当n=k时,命题成立,即n=k时,原数组中任何一个元素在任何一个位置的概率为1/k。

     则当n=k+1时,当算法执行完k次时,前k个元素在前k个位置的概率均为1/k。

     当执行最后一步时,前k个元素中任何一个元素被替换到第k+1位置的概率为:(1-1/(k+1)) * 1/k = 1/(k+1); 在前面k个位置任何一个位置的概率为(1-1/(k+1)) * 1/k = 1/(k+1);

    故前k个元素在任意位置的的概率都为1/(k+1)

     所以,对于前k个元素,它们在k+1的位置上概率为1/(k+1)。

     对于第k+1个元素,其在原位置的概率为1/k+1,在前k个位置任何一个位置的概率为:(1-k/(k+1)) * (1/k)=1/(k+1),所以对于第k+1个元素,其在整个数组前k+1个位置上的概率也均为1/k+1。

     综上所述,对于任意n,只要按照方案中的方法,即可满足每个元素在任何一个位置出现的概率均为1/n。

     

    扩展:一道google面试题

    给定一个未知长度的整数流(数目大于1000),如何从中随机选取1000个随机数。

     

    解决方法:

    l  定义长度为1000的数组,对于数据流中的前1000个关键字,显然都要放到数组中。

    l  对于数据流中的的第n(n>1000)个关键字,则这个关键字被随机选中的概率为 1000/n。故以 1000/n 的概率用这个关键字去替换数组中的一个。这样就可以保证所有关键字都以 1000/n的概率被选中。对于后面的关键字都进行这样的处理,这样就可以保证数组中总是保存着1000个随机关键字。

     

    注:以1000/n的概率选择一个数替换,可通过rand() % n实现,则这个数被替换到前1000个位置中的概率为1000/n。

    转自:http://blog.chinaunix.net/uid-20196318-id-216658.html

  • 相关阅读:
    jQuery EasyUI API 中文文档 可调整尺寸
    jQuery EasyUI API 中文文档 链接按钮(LinkButton)
    jQuery EasyUI API 中文文档 手风琴(Accordion)
    jQuery EasyUI API 中文文档 表单(Form)
    jQuery EasyUI API 中文文档 组合(Combo)
    jQuery EasyUI API 中文文档 布局(Layout)
    jQuery EasyUI API 中文文档 拆分按钮(SplitButton)
    jQuery EasyUI API 中文文档 菜单按钮(MenuButton)
    jQuery EasyUI API 中文文档 搜索框
    jQuery EasyUI API 中文文档 验证框(ValidateBox)
  • 原文地址:https://www.cnblogs.com/freeopen/p/5482894.html
Copyright © 2011-2022 走看看