给定一个数组,需要打乱其顺序,保证每个元素在任意位置出现的概率相等?
- 对于A[i],i=0,1,2,…N,随机在数组A[i,i+1,…N]中挑选一个数字交换到A[i]。
- 证明算法随机,只需证明每个数字分配到每个位置的概率是相等的。
- 易得,数组0-N位置的任意一个数字到位置0的概率都是1/n;
到位置1的概率是(1-1/n)*(1/(n-1))=1/n - 解释:P(到位置1)=P(第一次调用随机算法的时候没交换到位置0)P(第二次到位置1|第一次调用随机算法的时候没交换到位置0)到位置2的概率是(1-1/n)(1-1/(n-1))(1/n-2)=1/n
package test;
import java.util.Random;
public class ShuffleArray {
public static void printArray(int[] arr){
for(int i=0;i<arr.length;i++){
System.out.print(arr[i]+" ");
System.out.println();
}
}
public static void shuffle(int[] arr){
for(int i=0;i<arr.length;i++){
Random r=new Random();
int index= r.nextInt(arr.length-i)+i;
int tmp=arr[i];
arr[i]=arr[index];
arr[index]=tmp;
}
}
public static void main(String[] args) {
int[] arr={
0,1,2,3,4};
int[][] count=new int[arr.length][arr.length];
double num=10000000.0;
for(int i=0;i<10000000;i++){
shuffle(arr);
for(int j=0;j<arr.length;j++){
count[arr[j]][j]++;
}
}
for(int i=0;i<arr.length;i++){
for(int j=0;j<arr.length;j++){
System.out.println("元素"+i+"出现在下标"+j+"的概率是:"+count[i][j]/num);
}
}
}
}
执行10000000次之后统计结果如下:
元素0出现在下标0的概率是:0.2000008
元素0出现在下标1的概率是:0.1998662
元素0出现在下标2的概率是:0.1999275
元素0出现在下标3的概率是:0.2001135
元素0出现在下标4的概率是:0.200092
元素1出现在下标0的概率是:0.199912
元素1出现在下标1的概率是:0.2003179
元素1出现在下标2的概率是:0.1999964
元素1出现在下标3的概率是:0.2000117
元素1出现在下标4的概率是:0.199762
元素2出现在下标0的概率是:0.2000958
元素2出现在下标1的概率是:0.2000629
元素2出现在下标2的概率是:0.1999091
元素2出现在下标3的概率是:0.1999877
元素2出现在下标4的概率是:0.1999445
元素3出现在下标0的概率是:0.2000743
元素3出现在下标1的概率是:0.1998193
元素3出现在下标2的概率是:0.2002315
元素3出现在下标3的概率是:0.1998692
元素3出现在下标4的概率是:0.2000057
元素4出现在下标0的概率是:0.1999171
元素4出现在下标1的概率是:0.1999337
元素4出现在下标2的概率是:0.1999355
元素4出现在下标3的概率是:0.2000179
元素4出现在下标4的概率是:0.2001958