实现不重复取数两种算法(洗牌算法)

在做游戏的时候碰到一个问题:从数组int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}中随机取16个不同的数,即对数组取一个随机排列,生成一个新的数组

方法一:开始想到的方法是从1-16中每次随机取出一个数,放到sourceArray 数组中去,同时将获得的随机数放到outArray 数组中,然后再随机取数,先与outArray 数组中进行一一比较,如果已经存在,重新随机取数。

该方法简单易懂,但时间复杂度与空间复杂度都比较大、、、

方法二:去网上搜索,知道这叫做洗牌算法,有多种方法实现。最终感觉这种方法简单易懂,计算量小。

方法是多次随机交换数组中的两个值,交换次数越多,越随机。

源代码:


public class RandomArray {
 /**
  * 类RandomArray,测试产生随机数组类
  * @author 张世民
  * 创建时间 2011-8-2
  * */
 
 public static void main(String[] args){
  System.out.println("----------------");
  //randomArray2(new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16});
  randomArray1();
 }
 
 public static void randomArray1(){
  int time = 0;//计算循环次数
  int[] sourceArray = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
   int[] outArray = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
  int i = 0;
  while(i < 16){
   int flag = 0;
   int index = (int) (Math.random()*sourceArray.length + 1);
   for(int j = 0; j < outArray.length; j ++){
     time ++;
    if(outArray[j] == index){
     flag = 1;
     break;
    } 
    else flag = 0;
   }
   if(flag == 0){
    sourceArray[i] = index;
    outArray[i] = index;
    i++;
    System.out.println(index);
   }
  } 
  System.out.println(time);
 }
 
 public static void randomArray2(int[] sourceArray){
  System.out.println("----------------");
  int tmp = 0;
  int p1, p2;
  int cnt = 20;//随机交换次数,在合适范围内,值越大越随机
  while(cnt > 0){
   p1 = (int) (Math.random()*sourceArray.length);
   p2 = (int) (Math.random()*sourceArray.length);
   tmp = sourceArray[p1];
   sourceArray[p1] = sourceArray[p2];
   sourceArray[p2] = tmp;
   cnt--;
  }
  for(int i = 0; i < 16; i++){
   System.out.println(sourceArray[i]);
  }
 }
}

再碰到其他方法时再添加

原文地址:https://www.cnblogs.com/zsmhhfy/p/2256287.html