不重复的随机数生成问题!
下面是我生成1到100之间不重复的随机数呢的代码,(规定用数组,不是用其它集合框架)可是总有一个回重复,不知道问题在哪里,请指点一二,谢谢:
代码:
import java.util.*;
public class Test {
public static void main(String[] args) {
int[] ints = new int[100];
for(int i=0;i<100;i++) {
int temp = (int) (Math.random()*100+1);
for(int j=0;j<100;j++) {
if(temp==ints[j]) {
temp = (int) (Math.random()*100+1);
j=0;
}
}
ints[i]=temp;
}
Arrays.sort(ints);
for(int index:ints) {
if(index%10==0)
System.out.println();
System.out.print(index+" ");
}
}
}
[解决办法]
第二个循环for(int j=0;j <100;j++)
改成for(int j=0;j <i;j++) 就可以了
[解决办法]
你这个代码效率太低,看看我BLOG中洗牌和数独的代码会对你有很大的启发
[解决办法]
很简单的问题,呵呵,一说破就大家都明白了。
这个问题的实际应用就比如要随机生成一副扑克牌,54张,顺序是乱的,但显然牌面不能重复。用随机数生成器生成的数总是会重复的,所以,不能把生成的数直接保存下来作为结果。那么怎么办?
你想想,如果是真实的扑克牌,你是怎么打乱的?你会说:洗牌啊!没错,就是洗牌!洗牌是什么过程?说白了,是交换!把两摞牌交换位置,用类似的方法就可以解决楼主的问题。
先按顺序在数组里生成1-100的数,然后产生一对0-99之间的随机数,把这两个数所表示下标的数交换位置,如此重复几十次,原先的数组就被打乱了。
[解决办法]
Math.random()生成的随机数能保证不重复吗?
[解决办法]
manbaum 的说法有一定道理,不过有一点不完整。
用“洗牌”方法最关键的一点,就是要抽出多少对数据交换多少次,简称(洗多少次牌?)。
理论上,至少洗 n/2 次才能洗到所有的牌。
但是,事实上,如果只洗 n/2 次,出现 没洗完所有牌 的几率很大
当然,如果出现一张至几张牌 还是在原来的位置,这种情况是绝对允许的。
下面,我贴了个算法,得出三组数据 比较两种 取随机数的方法。
数据表示有多少个数据在原位置上
取n/2对数据交换
0 0 0 2 2 2 3 1 0 1
375 346 361 371 370 380 378 378 358 367
取n对数据交换
0 2 0 2 1 0 0 2 1 1
120 139 147 147 126 133 144 139 132 140
取n*n对数据交换
2 2 0 0 0 2 1 0 1 1
0 1 0 0 3 2 1 0 0 1
public class Main { public Main () { start (); } public static void main (String[] args) { new Main (); } private void start () { for (int i = 0; i < m; i++) { // for (int j = 0; j < n; j++) { iarr[j] = 0; } iarr_1[i][0] = g_1 (); // for (int j = 0; j < n; j++) { iarr[j] = j; } iarr_1[i][1] = g_2 (); } for (int i = 0; i < 2; i++) { for (int j = 0; j < m; j++) { System.out.printf("%1$5s", iarr_1[j][i]); } System.out.println(""); } } private int g_1 () { int j = 0; while(j < n-1) { int x = r.nextInt (n); if (iarr[x] == 0) { j++; iarr[x] = j; } } return check (); } private int g_2 () { for (int i = 0; i < n*n; i++) { int x = r.nextInt (n); int y = r.nextInt (n); { int c = iarr[x]; iarr[x] = iarr[y]; iarr[y] = c; } } return check (); } private int check () { int j = 0; for (int i = 0; i < n; i++) { if (iarr[i] == i) { j++; } } return j; } private final int n = 1000; private int[] iarr = new int[n]; private final int m = 10; private int[][] iarr_1 = new int[m][2]; private java.util.Random r = new java.util.Random ();}
------解决方案--------------------
先产生一个随机数,放到一个数组里,然后再产生一个,与数组里的数比较,相同的话就继续产生新的随机数,不相同的话就先放到数组里,然后再产生下个随机数.
这样就能保证不重复了,但是这样的算法效率十分的低!!
[解决办法]
你重复的都是第一个打印出来的数字,只要将
temp = (int) (Math.random()*100+1);
j=0;
中的j=0;改成j=-1就可以了。
[解决办法]
这里有一个算法,可以保证随机性, 而且复杂度是O(n)。
基本思想就是for each i:1-->n, swap(value[i], value[random(i, n)])
对于第i次随机选到的元素,有i个独立的随机事件,分别是i-1次未选中和1次选中
事件发生的概率=((n-1)/n)*((n-2)/(n-1))* …… *((n-i+1)/(n-i+2))*(1/(n-i+1)) = 1/n
所以每个元素的事件发生都是等概率的,而且时间复杂度线性。
这是算法导论上的一个例子
import java.util.*;
public class Randomize
{
public static final int MAX_SIZE = 100;
public static final int MAX_VALUE = 100;
public static void main(String [] args)
{
//Initialize the array
int [] value = new int[MAX_SIZE];
for(int i=0; i<value.length; i++)
{
value[i] = i+1;
}
//Randomize the Array
randomize(value);
for(int i=0; i<value.length; i++)
{
if(i%10 == 0)
System.out.println("");
System.out.print(value[i]+" ");
}
}
public static void randomize(int [] value)
{
Random r = new Random();
for(int i=0; i<value.length-1; i++)
{
int index = r.nextInt(MAX_VALUE-i)+i;
int temp = value[i];
value[i] = value[index];
value[index] = temp;
}
}
}
[解决办法]
import java.util.*;
public class Randomize
{
public static final int MAX_SIZE = 100;
public static final int MAX_VALUE = 100;
public static void main(String [] args)
{
//Initialize the array
int [] value = new int[MAX_SIZE];
for(int i=0; i <value.length; i++)
{
value[i] = i+1;
}
//Randomize the Array
randomize(value);
for(int i=0; i <value.length; i++)
{
if(i%10 == 0)
System.out.println("");
System.out.print(value[i]+" ");
}
}
public static void randomize(int [] value)
{
Random r = new Random();
for(int i=0; i <value.length-1; i++)
{
int index = r.nextInt(MAX_VALUE);
int temp = value[i];
value[i] = value[index];
value[index] = temp;
}
}
}