C++高效率在m个元素中随机取n个元素的算法

一、简述

在编程中,尤其是编写游戏的过程中经常会遇到在m个东西中取出n个东西的需求,这个时候一般人都会想到随机n个数出来,然后在原来的列表中去凑这n个数的下标。这样会导致许多的问题,例如很难保证不出现重复的随机数,更重要的是我们会为了避免这些问题去做许多没有意义的循环从而严重的影响了效率,这个时候就需要一个更加有效率的算法。

二、基本原理

如果我们总共有的个数为m,而我们需要随机取出的个数为n。
那么我们每一个元素被取出的概率为: n m \frac{n}{m} mn​
如果我们已经取出了一个元素,那么下一个元素被取出的概率为: n − 1 m − 1 \frac{n-1}{m-1} m−1n−1​
如果我们这一次未取出一个元素,那么下一个元素被取出的概率为: n m − 1 \frac{n}{m-1} m−1n​
可以看出当一个元素被取出来的时候,下一个元素被取出来的概率就会降低,而当一个元素未被取出来的时候,下一个元素被取出的概率就会提高。
这时我们就可以推导出每一个元素被取出的概率为:
要 取 的 个 数 − 已 经 取 出 的 个 数 总 数 − 已 经 遍 历 的 个 数 \frac{要取的个数-已经取出的个数}{总数-已经遍历的个数} 总数−已经遍历的个数要取的个数−已经取出的个数​

这个地方除数如果忘了减去已遍历的个数会导致每一个元素取出的概率依次降低
当要取的个数等于已经取出的个数时我们就可以结束随机。
可以很容易地得出从全局来看每一个元素的取出概率都是相同的,且仅需要一次循环就可以满足需求,时间复杂度为O(n)。

三、示例

例如:在10*10的扫雷棋盘上随机布30个雷的随机算法:

这里我们控制台创建一个10*10的矩阵,用“1”表示布下雷,“0”表示没有雷
C++代码如下:

#include <iostream>
#include<time.h>int main(int argc, char const *argv[])
{int _nMaxNum=100;//所有的个数int _nNeedNum=30;//要取的个数int _nHaveNum=0;//已经取得的个数int _nIndex=0;//已遍历的个数srand((unsigned)time(NULL));for(int i=0;i<10;i++){for(int j=0;j<10;j++){if(rand()/(double)RAND_MAX < ((double)_nNeedNum - (double)_nHaveNum) / ((double)_nMaxNum - (double)_nIndex)){std::cout<<1<<" ";_nHaveNum++;//  if(_nNeedNum==_nHaveNum){//      break;//  }这里因为要完整绘制棋盘所以不用}else{std::cout<<0<<" ";}_nIndex++;}std::cout<<std::endl;}
}

运行结果:

该算法可以同样推广至其他场景。

C++高效率在m个单位中随机取n个单位的算法相关推荐

  1. spring 数组中随机取几个_游戏编程中需要掌握哪些数学物理知识

    一. 相似三角形知识的应用 在摇杆控制物体运动的游戏中,摇杆的手柄(下图黄色圆饼),不能移出摇杆所在的套(下图灰色圆环),也就是说摇杆偏离中心点的最大距离为max_R.一旦触摸移动过程中移动的点超出此 ...

  2. python权重是什么意思_在python带权重的列表中随机取值的方法

    1 random.choice python random模块的choice方法随机选择某个元素 foo = ['a', 'b', 'c', 'd', 'e'] from random import ...

  3. python中怎么随机从字典中取值_python怎样从字典中随机取数据

    python从字典中随机取数据的方法:可以利用random.sample()函数来实现.random.sample()函数多用于截取列表的指定长度的随机数,但是不会改变列表本身的排序. random. ...

  4. spring 数组中随机取几个_准备几个月,面试阿里耗时两周,最终凭借这些知识拿下阿里offer...

    朋友去阿里进行的技术面,历经了二个多小时,面试的是Java开发工程师,出来后立马拿手机记录了面试问的知识点,知识点包括Java基础和高级.spring.多线程.网络.数据库.算法.Redis.分布式. ...

  5. spring 数组中随机取几个_美团Java研发三面(3年经验):MySQL+Spring源码+分布式+算法+线程...

    虽然自己记性不太好,但还是记录了一下,热乎乎的面经啊,也有一些问题没能记住.三面技术面经如下: 美团一面: 中间省略掉大概几个问题,因为我不记得了,下面记得的基本都是我没怎么答好的. 了解SOA,微服 ...

  6. spring 数组中随机取几个_别给孩子取这三种名字!截止年末,名字中的这几个字已经烂大街了...

    随着时代的进步,科技的发展,人们的生活水平不断,提高,许多的家庭都在拥有了不错的生活条件之后选择培养自己的下一代,随着宝宝的到来让整个家庭变得更加幸福,然而,许多家长却在给宝宝起名字这件事上放了愁,对 ...

  7. c语言随机生成n个数求最小值,C语言程序:从N个数中随机取出100个不同的数

    /**你题目中的N个数至少得大于100吧.下面的程序N个数是随机生成 你的N个数是?同时这个程序有错误的话请告诉我. */ /* *从N个数中随机取出100个不同的数 *@author:banxi19 ...

  8. 从数组中随机选择一条

    /**从数组中随机取一个数据出来*/ function getRandom(arr) {var len = arr.length;var i = Math.ceil(Math.random() * ( ...

  9. 计算机中表格怎么用英语说,电脑excel表格如何在表格中随机生成一个大写英文字母...

    电脑excel表格如何在表格中随机生成一个大写英文字母 我们可以利用一个函数(在表格中随机生成大写字母)来帮助我们制作英文练习本,今天小编就告诉大家电脑excel表格如何在表格中随机生成一个大写英文字 ...

最新文章

  1. C 回顾 volatile 和 register 修饰符
  2. 开源跨平台移动项目Ngui【Action动作系统】
  3. markdown 常用格式
  4. html实战例子: 课程表
  5. 深圳店匠笔试题-4.01
  6. Google Guava新手教程
  7. CODE[VS] 1346 HelloWorld编译器
  8. Composer帮你轻松管理PHP包 autoload
  9. JAVA写的多线程下载程序,并具有断点续传功能
  10. zz详细讲解Quartz.NET
  11. 《移动网页设计与开发 HTML5+CSS3+JavaScript》—— 1.4  真正的HTML5
  12. 定向寻宝亲子活动设计思路和实操(附2019最新教程)
  13. 位图转换G代码小程序
  14. 数据传输服务器系统图,档案数字化管理系统
  15. centos linux7 开启桌面命令,centos7如何在桌面打开终端
  16. mysql jdbc dao_MYSQL 之 JDBC(九):增删改查(七)DAO的补充和重构
  17. 一个IT技术经理需要具备的素质
  18. [proxy:0:0@WORKSTATION-DEV] HYDU_sock_write (utils/sock/sock.c:256): write error (Broken pipe)
  19. 正睿OIday3总结
  20. 第一周学习前端html的知识总结与感悟

热门文章

  1. 代码统计分析工具SourceCounter
  2. make-ipinyou-data 的 Python3更改
  3. 效果惊艳的开源动画库,不仅牛逼,还很小巧
  4. 红外通信模块、NEC红外收发模块(2)——两个红外模块交互信息
  5. 树莓派语音+红外模块实现智能家居实践
  6. 传统的企业如何才能转型成功
  7. 蛇蛇大作战-进度条0
  8. 怎么查oracle ocm证书,Oracle OCM认证
  9. java毕业设计动漫网站Mybatis+系统+数据库+调试部署
  10. threejs导入模型为黑色原因