package com.interview.algorithms.array;
import java.util.Random;
import com.interview.utils.ArrayUtil;
import com.interview.utils.ConsoleReader;
/**
* 问题: 给定一个有序序列1~n,要你将其完全打乱,要求每个元素在任何一个位置出现的概率均为1/n。<br>
解决方案:依次遍历数组,对第k+1个元素,以1/k的概率与前k个元素中的某个元素互换位置,最后生成的序列即满足要求。<br>
使用数学归纳法证明:<br>
1) 当n=1时,元素arr[0]在任何一个位置的概率为1/1,命题成立。<br>
2) 假设当n=k时,命题成立,即n=k时,原数组中任何一个元素在任何一个位置的概率为1/k。<br>
则当n=k+1时,当算法执行完k次时,前k个元素在前k个位置的概率均为1/k。<br>
当执行最后一步时,前k个元素中任何一个元素被替换到第k+1位置的概率为:(1-1/(k+1)) * 1/k = 1/(k+1); <br>
在前面k个位置任何一个位置的概率为(1-1/(k+1)) * 1/k = 1/(k+1); <br>
故前k个元素在任意位置的的概率都为1/(k+1); <br>
所以,对于前k个元素,它们在k+1的位置上概率为1/(k+1)。<br>
对于第k+1个元素,其在原位置的概率为1/k+1,在前k个位置任何一个位置的概率为:(1-k/(k+1)) * (1/k)=1/(k+1)<br>
所以对于第k+1个元素,其在整个数组前k+1个位置上的概率也均为1/k+1。<br>
3) 综上所述,对于任意n,只要按照方案中的方法,即可满足每个元素在任何一个位置出现的概率均为1/n。<br>
*
* @author zouzhile (zouzhile@gmail.com)
*
*/
public class C4_11_RandomShuffle {
public static void shuffle(int[] array){
Random random = new Random();
for(int i = 1; i < array.length; i ++){
int randomIndex = random.nextInt(i + 1);
ArrayUtil.swap(array, randomIndex, i);
}
}
public static void main(String[] args){
System.out.println("The Random Shuffle Implementation");
System.out.println("========================================================================");
ConsoleReader reader = new ConsoleReader();
System.out.print("Please input the int array elements: ");
int[] array = reader.readIntItems();
System.out.println();
C4_11_RandomShuffle shuffler = new C4_11_RandomShuffle();
System.out.print("The shuffled array is : ");
for(int i = 0; i < 10; i++){
int[] clone = array.clone();
shuffler.shuffle(clone);
for(int j: clone){
System.out.print(" " + j);
}
System.out.println();
}
}
}