/**
*
*問題或許可以是這樣:產生m個隨機正整數,要求范圍是從1到n,平且它們互不相同。
問題或許可以這樣解決:
假設我們已經有了經過排序的(升序),且滿足要求的k個正整數,我們繼續:
1、在從1到n-k的區間范圍內,產生一個隨機的正整數i1;
2、統計在已有序列中比i1小的數,將其個數加到i1上,得到i2;再統計從i1到i2數的個數,得到i3;一直循環,直到i不變為止。然后,把i插入已有的序列。這個過程相當于從頭數出i1個空白,以此來保證新的數是隨機的。
3、這時得到了k+1個滿足要求的數,然后就循環吧。
上面的方法適用于n很大,但是m很小的時候。
如果m和n都很大,并且希望一次性的產生,那么:
1先產生有一定冗余的隨機正整數,然后排序,然后去掉相同的數。
如果,產生了超額的數,可以將數列再打亂順序,然后,取出符合規定的數目的數。
當然,也可以兩種方法相結合,就是:
1、先產生超過需求的、有一定冗余的隨機正整數,然后排序,然后去掉相同的數,并且保存下來。記錄它的數目m1 >m;
2、當要用時,在產生一個從1到m的隨機數j,然后取出數據庫中第j個數,輸出,并且把它從數據庫中刪除到。
*
*
*
*
*
*
*
*
*數據有點大,用了128m
start_1 (); 是即時輸出(因為用boolean數組,所以內存小得多)
start_2 (); 是把數據存進數組,以便再處理(需要內存很大,不贊成使用)
如果要處理數據,可以用 start_1 (); 把數據保存進文件,再從文件中讀取數據進行處理。
*/
public class Main{
public final int n = 10000000;
public Main () {
start_1();
//start_2 ();
}
public static void main (String[] args) {
new Main();
}
public void start_1() {
//布朗型默認為 false
boolean[] barr = new boolean[n];
//
java.util.Random r = new java.util.Random ();
int j = 0, x;
int m = n;
while(j < m) {
x = r.nextInt (n);
if (! barr[x]) {
j++;
barr[x] = true;
System.out.println (x);
}
}
}
public void start_2() {
//整型默認為 0
int[] iarr = new int[n];
//
java.util.Random r = new java.util.Random ();
int j = 0, x;
int m = n;
//少循環一次,因為要生成 0
while(j < m-1) {
x = r.nextInt (n);
if (iarr[x] == 0) {
j++;
iarr[x] = j;
}
}
}
}
/*
*上面的算法,沒有優化,生成數據耗時間。
下面的算法改進了一下。生成所有數據半分鐘左右。
+----------
| 0...999999
| .
| .
| .
| 99
Java code
public class Main {
public Main () {
start_1 ();
start_2 ();
}
public static void main (String[] args) {
new Main ();
}
** void start_1 () {
for (int i = 0; i < n; i++) {
byte j = 0;
while(j < m-1) {
int x = r.nextInt (m);
if (barr_1[x] == 0) {
j++;
barr_1[x] = j;
}
}
}
}
** void start_2 () {
int j = 0;
while(j < n) {
int x = r.nextInt (n);
int y = (int) barr_2[x];
if (y < m) {
j++;
barr_2[x]++;
int z = ((int) barr_1[x][y]) * n;
//System.out.println (x + z);
}
}
}
** final int s = 10000*10000;
** final int m = 100;
** final int n = s/m;
** byte[][] barr_1 = new byte[n][m];
** byte[] barr_2 = new byte[n];
** java.util.Random r = new java.util.Random ();
}
*/
/*
*和一位仁兄在另一個帖子爭論中,受到啟發。
終于悟出一種時間復雜度極低的算法。
(可以證明,任意一個數 在 任意位置的概率 都為 1/n)
因為內存不夠,所以改成了7個9來算。總時間2秒
Java code
public class Main {
public Main () {
start ();
}
public static void main (String args[]) {
new Main ();
}
** void start () {
java.util.Random r = new java.util.Random ();
for (int i = 0; i < n; i++) {
int x = r.nextInt (i+1);
iarr = iarr[x];
iarr[x] = i;
}
//
int m = 10;
for (int i = 0; i < m; i++) {
System.out.print (iarr + " ");
}
}
** final int n = 1000*10000;
** int[] iarr = new int[n];
}
*/
posted on 2008-02-01 11:20
lk 閱讀(782)
評論(0) 編輯 收藏 所屬分類:
j2se