Preface:
這邊要產生不重覆亂數的方法,下面是三種方式,只要是暴力法都很慢,速度是O(n^2). Java要產生亂數很簡單,只要呼叫 Random 類別就可以了,不過如果想要不重覆的亂數,有一些小方法可以用,這裡提供三種方法.
暴力比對法:
這個 GenerateDuplicateRan 方法會接收一個整數,表示你要取得亂數的範圍,丟進去100表示你要取0~99之間的亂數:
- public static int[] GenerateNonDuplicateRan1(int range)
- {
- Random rand = new Random();
- int rdm[] = new int[range];
- List
holeList = new ArrayList (); - for(int i=0; i
- for(int i=0; i
- {
- int pv=-1;
- do{
- pv = (int)(rand.nextDouble()*range);
- }while(!holeList.remove(Integer.valueOf(pv)));
- rdm[i] = pv;
- }
- return rdm;
- }
Collection移出法:
第二種方法就快多了,尤其在產生大量亂數的時候更為明顯。分成三個部分來解釋.
1. 產生一個ArrayList,並且利用for loop塞值進去,你想要產生0~99的亂數,就丟100進去,他就會依序把0~99塞到ArrayList裡面.
2. 用Collection的remove method,隨機的取index,並且移出,直到 ArrayList 的size = 0。因為本來在ArrayList裡面的數字就沒有重複(用for loop塞的),所以隨機取出的值也不會重複!
3. 最後一個部份就是去呼叫上面的方法並且宣告一個array來接收上面產生的亂數
函數 GenerateNonDuplicateRan2 代碼如下:
- public static int[] GenerateNonDuplicateRan2(int range)
- {
- Random rand = new Random();
- int rdm[] = new int[range];
- List
holeList = new ArrayList (); - for(int i=0; i
- int cnt=0;
- while(holeList.size()>0)
- {
- int pv = holeList.remove(rand.nextInt(holeList.size()));
- rdm[cnt++] = pv;
- }
- return rdm;
- }
另一種方式是使用 HashSet unique element 的特性, 每次產生一個 random 的整數去比對 HashSet 是否已經看過, 否則就從新產生一個 random 的整數; 如果沒看過, 便將該整數加到 HashSet 與 返回的 整數陣列中:
- public static int[] GenerateNonDuplicateRan3(int range)
- {
- int rdm[] = new int[range];
- Random rand = new Random();
- HashSet
set = new HashSet (); - for(int i=0; i
- {
- int pv = -1;
- do
- {
- pv = rand.nextInt(range);
- }while(!set.add(pv));
- rdm[i] = pv;
- }
- return rdm;
- }
底下是三種方法的使用代碼:
- public static void main(String args[])
- {
- int range = 1000;
- long st = System.currentTimeMillis();
- int[] rdm = Rdm.GenerateNonDuplicateRan1(range);
- System.out.printf("\t[Info] GenerateNonDuplicateRan1 with Range=%d:\n", range);
- long ut = System.currentTimeMillis()-st;
- for(int i:rdm) System.out.printf("%d ", i);
- System.out.println();
- System.out.printf("\t[Info] Spending time=%d ms(%d)!\n\n", ut, rdm.length);
- st = System.currentTimeMillis();
- rdm = Rdm.GenerateNonDuplicateRan2(range);
- System.out.printf("\t[Info] GenerateNonDuplicateRan2 with Range=%d:\n", range);
- ut = System.currentTimeMillis()-st;
- for(int i:rdm) System.out.printf("%d ", i);
- System.out.println();
- System.out.printf("\t[Info] Spending time=%d ms!(%d)\n\n", ut, rdm.length);
- st = System.currentTimeMillis();
- rdm = Rdm.GenerateNonDuplicateRan3(range);
- System.out.printf("\t[Info] GenerateNonDuplicateRan3 with Range=%d:\n", range);
- ut = System.currentTimeMillis()-st;
- for(int i:rdm) System.out.printf("%d ", i);
- System.out.println();
- System.out.printf("\t[Info] Spending time=%d ms!(%d)\n\n", ut, rdm.length);
- }
可以看的出來第二種方法最快!
沒有留言:
張貼留言