关于循环次数的一道题

Posted 加油!!!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于循环次数的一道题相关的知识,希望对你有一定的参考价值。

下面的程序可以从0....n-1中随机等概率的输出m个不重复的数。这里我们假设n远大于m
1
2
3
4
5
6
7
8
9
10
knuth(int n, int m)
    srand((unsigned int)time(0)); 
    for (int i = 0; i < n; i++) { 
        if ( ) { 
            cout << i << endl;
            ( );
        }
     }
}

正确答案: B   你的答案: A (错误)

rand()%(n-i)<=m   m--
rand()%(n-i)<m   m--
rand()%(n-i)>=m   m++
rand()%(n-i)>m   m++
为了方便解释假设n等于10,m等于5:
第一次rand()%(n-0)的余数范围是0~9,有可能小于m(=5),可以输出i=0;随后i++,m--
第二次rand()%(n-1)的余数范围是0~8,有可能小于m(=4),可以输出i=1;随后i++,m--
...
第五次rand()%(n-4)的余数范围是0~5,有可能小于m(=1),可以输出i=4;随后i++,m--得到i=5,m=0

第六次rand()%(n-5)的余数范围是0~4,不可能小于m(=0),算法结束。

倘若rand()%(n-i)<=m,则第六次还满足条件,意味着多输出的一次;

而rand()%(n-i)>=m,将会因为判断条件不满足而提早退出。因此选B
上面有的回答思路很正确,但概率表述有问题,在这跟大家分享下
由这个for循环循环n次,且在满足条件时才输出i,可知,输出m个不同值的要求已满足,因为每次输出的都是i值,而i值每次都是不一样的,m--保证了程序在输出了m个值后就停止循环。
在i=0时,rand()%(n-i)的取值范围为0到n-1,共n个数,此时要输出0只需要rand()%(n-i)小于m,故i=0被输出的概率为m/n;
在i=1时,rand()%(n-i)的取值范围为0到n-2,共n-1个数,若i=0没有被输出,则m--未被执行,此时i=1被输出的概率为m/(n-1),若i=0已经被输出了,则m变为m-1,此时i=1被输出的概率为(m-1)/(n-1);由概率论的知识,可知此时i=1被输出的概率为
P=(1-m/n)*(m/(n-1))+m/n*((m-1)/(n-1))=m/n;以此类推,可知每个数被输出的概率都为m/n

以上是关于关于循环次数的一道题的主要内容,如果未能解决你的问题,请参考以下文章

编辑距离(线性DP+暴力匹配)

一道题,最小操作次数使数组元素相等引发的思考

一道题,最小操作次数使数组元素相等引发的思考

一道题,最小操作次数使数组元素相等引发的思考

关于一道JS面试题的思考

关于静态代码块的执行顺序,很简单的一道题,应该所有人都会吧?