zoukankan      html  css  js  c++  java
  • 从M个数中随机等可能的取出N个的问题

    从0到m-1这m个数中随机取出n个(n<=m) 要求每个数被取到的可能性相等。 
    第一个方法是把这m个数丢到一个List里面 然后用nextInt(list.size())来产生随机数 然后把list里面对应的元素丢到另一个数组或者list里面 这个方法本来是不错的 但要注意的是 为了保证每个元素取到的概率相等 需要每取出一个元素 就把它从list里面删除 原因就不解释了 简单的概率问题。但众所周知的是 list的remove(int index)方法 效率并不高 尤其是当m和n很大的时候 每一次调用remove ArrayList都需要进行数组的copy 而LinkedList需要进行链表的遍历。 
    所以再考虑这个问题,用数组来储存这m个数是很好的 而且其实我们并不需要知道到底哪些下标的元素被选中了 第一个方法的效率低下的原因在于 nextInt(int i)这个方法是从0 到i-1随机生成整数 这里要求0到i-1是连续的i个整数 而我们选取了一个数之后 为了满足连续整数的条件 就要把这个数删去 而频繁删除的效率是低下的 所以换一种思路 不采用删除 而采用交换 

    第二个方法 比如0-99这100个数字 从小到大放在一个数组里面 现在要选10个 我们只需要随机打乱这个数组 然后选取前10个元素就好 随机打乱的方法就是 从数组头元素开始 每次产生一个随机数n 然后交换这两个数 而且只需要交换十次就够了 因为我们并不取下标超过10后面的数字 

    import java.util.Random;  
      
      
      
    public class Rand {  
      
        public static void randSelect(int[] nums, int n) {  
            Random rand = new Random();  
            for(int i = 0; i < n; i ++){  
                swap(nums , i, rand.nextInt(nums.length-i)+i);  
            }  
        }  
          
        public static void swap(int[] nums, int m , int n){  
            int temp = nums[n];  
            nums[n] = nums[m];  
            nums[m] = temp;  
        }  
      
        public static void main(String[] args) {  
            int[] nums = new int[100];  
            for(int i = 0;i < 100;i++){  
                nums[i]=i;  
            }  
            randSelect(nums,10);  
            for(int i = 0;i < 10; i ++){  
                System.out.println(nums[i]);  
            }  
        }  
    }  
      
    /*output :&nbsp; 
    27 
    79 
    30 
    58 
    41 
    54 
    75 
    18 
    26 
    5 
    */  
  • 相关阅读:
    ASP.NET MVC请求处理管道生命周期的19个关键环节(13-19)
    ASP.NET MVC请求处理管道生命周期的19个关键环节(7-12)
    ASP.NET MVC请求处理管道生命周期的19个关键环节(1-6)
    关于领域模型
    WebForm和MVC的一些知识(转)
    抽象工厂
    SCP,scp linux2台机器之间如何传输文件
    mysql卸载(windows)【转】
    (5.2.3)配置服务器参数——服务器性能估算
    Windows命令行使用FTP
  • 原文地址:https://www.cnblogs.com/mr-wuxiansheng/p/6851985.html
Copyright © 2011-2022 走看看