经典的面试题: 产生一个int数组,长度为100,并向其中随机插入1-100,并且不能重复
网上实现的方法也千奇百怪.
实现思路:
(1)把N个数放入Hashtable 或者arrayList 中.
(2)从上面的集合中随机抽取一个数放入int数组中.
(3)把取出的这个数从上面的集合中删除.
(4)循环 (2),(3) 步骤,直到int数组取满为止.
我们一般都会想到这种做法,但是当Hashtable或者ArrayList中放几千万,几亿数据时,这时从集合中删除元素将严重影响性能,如果突破此瓶颈? 网上找到一种更好的方法.
(1)把N个数放到容器A(int数组)中.
(2)从N个数中随机取出1个数放入容器B(int数组)中.
(3)把容器A中最后一个数与随机抽取的数对调 或者 把容器A中最后一个数覆盖随机抽取出来的数.
(4)这时从容器A(假设N个数,索引0 到 索引N-2)之间随机取一个数.再放入容器B中,重复此步骤.
说明:也就是第二次是从容器A中 第一个元素到倒数第二个元素 中随机取一个数.
这种好处是,随机数所取范围逐步缩小,而且杜绝了大数据时集合执行删除操作时产生的瓶颈.
下面给出DEMO(这里的是将容器B中最后一个数覆盖所取的随机数)
public static int[] GetNumber(int total) { int[] NumberBox = new int[total];//容器A int[] rtnNumber = new int[total];//容器B for (int i = 0; i < total; i++) { NumberBox[i] = i;//先把N个数放入容器A中 } Random rad = new Random(); int end = total - 1; for (int j = 0; j < total; j++) { int num = rad.Next(0, end + 1);//取随机数 rtnNumber[j] = NumberBox[num];//把随机数放入容器B NumberBox[num] = NumberBox[end];//把容器A中最后一个数覆盖所取的随机数 end--;//缩小随机数所取范围 } return rtnNumber;//返回int型数组 }