1. 程式人生 > >關於隨機數(不重複)

關於隨機數(不重複)

方法一

一般思路,大多數人也是網上比較多的:確定一個存一個。思路比較簡單,直接上摘過來的程式碼。

 //網上方法獲取不重複隨機數
    private static void testA(int sz){
        long startTime=System.currentTimeMillis(); //開始測試時間
        Random random = new Random();
        int a[] = new int[sz];//隨機陣列
        for (int i = 0; i < a.length; i++) {
            a[i] = random.nextInt(sz);
            for (int j = 0; j < i; j++) {
                while (a[i] == a[j]) {//如果重複,退回去重新生成隨機數
                    i--;
                }
            }
        }
        long endTime=System.currentTimeMillis(); //獲取結束時間 
        System.out.println("網上思路程式碼執行時間: "+(endTime-startTime)+"ms"); 
    }

方法二

第一種方法一般很容易想到,然後我想了想還有沒有別的方法,一時間想不出來就去網上搜搜,結果大多數都是第一種,然後在一個網站上看到了一位寫了另一種方法,用到了集合。先上他的程式碼,網站在最後貼出來。

private static void testB(int sz){
        long startTime=System.currentTimeMillis(); //開始測試時間
        Random rd = new Random();
        int[] rds = new int[sz];//隨機數陣列
        int n = 0;//序號
        List<Integer> lst = new ArrayList<Integer>();//存放有序數字集合
        //獲取隨機數陣列, 裡面有重複數字
        while (n < rds.length) {
            lst.add(n);
            rds[n++] = rd.nextInt(sz);
        }
        //把隨機數和有序集合進行匹對, 把隨機數在集合出現的數字從集合中移除掉.
        for (int i = 0; i < rds.length; i++) {
            for (int j = 0; j < lst.size(); j++) {
                if (rds[i] == lst.get(j)) {
                    lst.remove(j);
                    break;
                }
            }
        }
        //把陣列中重複的第二個數字用集合的第一個數字替換掉, 並移除掉陣列的第一個數字
        for (int i = 0; i < rds.length; i++) {
            for (int j = 0; j < rds.length; j++) {
                if (i != j && rds[i] == rds[j]) {
                    rds[j] = lst.get(0);
                    lst.remove(0);
                    break;
                }
            }
        }
        //得到的  rds  陣列就是不重複的隨機陣列
        long endTime=System.currentTimeMillis(); //獲取結束時間
        System.out.println("自定義程式碼執行時間: "+(endTime-startTime)+"ms");
    }

第三種

按照他說的比第一種方法效能要好,尤其是在數越大的時候,這個我沒有測試。時我看完了還再想還有沒有其他方法,因為雖然效能好,但是程式碼量有點多了。結果昨天臨睡覺前想出來一個,很興奮,不過在今天下午就被澆了涼水。。。這是後話了。上個方法只是把有序的十個數打亂順序然後取出來,有時候可能需要在五十個數、一百個數、一千個數等等裡面取出若干的數,上面的方法可以再優化。再得到用集合的方法的啟發後,整體思路是:定義兩個變數來控制隨機數個數和隨機數取值範圍,動態定義隨機陣列,然後先用for迴圈將取值範圍按順序存入集合,也就是集合裡面的數就是可以取得的隨機數值。再用一個for迴圈來取十個數,迴圈內隨機一個範圍內的數作為下面集合裡的數值的下標,然後賦值給隨機陣列,再將這個值從集合中移除。在這裡用集合的好處體現出來了,當一個集合的一個元素被移除後,後面的會自動前移,即使下次隨機的下標和上一個一樣,得到的數值也不會重複。先上我自己寫出來的程式碼。

//count是要取的隨機數的個數,arround是隨機數在哪個範圍取 [0~arround)
public static int[] testA(int count, int arround){
        long time = System.currentTimeMillis();//依舊是測試時間。。。
        Random random = new Random();
        ArrayList<Integer> numList = new ArrayList<>();//集合存放可以取的數值範圍
        int[] rand = new int[count];//隨機陣列
        for (int i = 1; i < arround+1; i++) {
            numList.add(i);//迴圈把範圍內的數值順序放入結集合
        }
        for (int i = 0; i < count; i++) {
            int n = random.nextInt(arround - i); // 隨機範圍內的數作為集合的下標
            rand[i] = numList.get(n); //找到這下標的數值並賦值給隨機陣列
            numList.remove(n);把該值從陣列移除
        }
        long time2 = System.currentTimeMillis();
        System.out.println("testA執行時間: " + (time2 - time) + "ms");
        return rand;
    }

然後 

悲劇來了!! 

今天又去這個網站,然後看到了評論下面有個人也發了個方法,跟我這個差不多,但是有些一樣,去看過就知道了。啊啊啊啊,,,還以為發現了新大陸。。好吧,還是太年輕。。。隨機數應該還有別的方法吧,如果有人知道還望告知,謝謝!

不過思考了,就是值得的,畢竟也是靠自己(咳咳。。)寫出來的~加油~