從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 
*/  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM