欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java生成抽樣隨機(jī)數(shù)的多種算法

 更新時(shí)間:2016年10月24日 09:30:51   作者:Q-WHai  
本文主要介紹了java生成抽樣隨機(jī)數(shù)的多種算法,主要是基于random庫(kù)函數(shù)的,有需要的可以了解一下。

本章先講解Java隨機(jī)數(shù)的幾種產(chǎn)生方式,然后通過(guò)示例對(duì)其進(jìn)行演示。

概述:

這里你是不是會(huì)說(shuō),生成隨機(jī)數(shù)有什么難的?不就是直接使用Java封裝好了的random就行了么?當(dāng)然對(duì)于一般情況下是OK的,而且本文要說(shuō)明的這些算法也是基于這個(gè)random庫(kù)函數(shù)的。

本文主要是針對(duì)抽樣這一行為進(jìn)行的,而抽樣本身有一個(gè)隱含的規(guī)則就是不要有重復(fù)數(shù)據(jù)。好了,有了這些說(shuō)明。你可以先嘗試著用一些自己的想法來(lái)實(shí)現(xiàn)不重復(fù)地生成隨機(jī)數(shù)。

算法嘗試:

一些好的算法出現(xiàn),往往伴隨著一些不那么好的算法。但是對(duì)于效果不太好的算法,它們普遍有一個(gè)共性,方便理解和實(shí)現(xiàn)。下面是通過(guò)一個(gè)循序漸進(jìn)的方式來(lái)作一個(gè)簡(jiǎn)單地說(shuō)明。

第一次嘗試:樸素隨機(jī)算法

這個(gè)算法很好理解,就是隨機(jī)!每一次產(chǎn)生一個(gè)隨機(jī)數(shù),并加入集合。 

 private void simpleRandom(int start, int end, int count) { 
    System.out.println("樸素隨機(jī)算法:"); 
    StringBuffer buffer = new StringBuffer(); 
    for (int i = 0; i < count; i++) { 
      int random = NumberUtils.randomInteger(start, end); 
      buffer.append(i == 0 ? ("[" + random) : (", " + random)); 
    } 
    buffer.append("]"); 
    System.out.println(buffer); 
  } 

第二次嘗試:檢查存在性隨機(jī)算法

我們知道上面的方法有一個(gè)問(wèn)題,就是可能會(huì)有重復(fù)數(shù)據(jù)。于是,我們就想到,在生成一個(gè)隨機(jī)數(shù)的時(shí)候進(jìn)行檢查一下這個(gè)數(shù)是不是已經(jīng)存在了,如果存在了就重新生成。

private void checkRandom(int start, int end, int count) { 
    System.out.println("檢查存在性隨機(jī)算法:"); 
    StringBuffer buffer = new StringBuffer(); 
    List<Integer> save = new ArrayList<>(); 
    for (int i = 0; i < count; i++) { 
      int random = NumberUtils.randomInteger(start, end); 
      if (exits(save, random)) { 
        i--; 
        continue; 
      } 
       
      save.add(random); 
      buffer.append(i == 0 ? ("[" + random) : (", " + random)); 
    } 
    buffer.append("]"); 
    System.out.println(buffer); 
  } 

第三次嘗試:元素移除隨機(jī)算法

上面的算法已經(jīng)解決了數(shù)據(jù)重復(fù)的問(wèn)題。不過(guò),有一個(gè)很糟糕的問(wèn)題就是可能我們要花費(fèi)很長(zhǎng)的時(shí)間來(lái)生成抽樣隨機(jī)數(shù)(這個(gè)要看臉了。。。。)。

不過(guò),這里我們有了新想法。那就是在一個(gè)集合中去隨機(jī)一個(gè)數(shù),當(dāng)這個(gè)被選中的時(shí)候就remove掉,那么下次再隨機(jī)的時(shí)候是不是就不會(huì)再隨機(jī)到這個(gè)數(shù)了?這樣就很好地解決了隨機(jī)數(shù)的重復(fù)問(wèn)題。代碼如下:

 private void removeRandom(int start, int end, int count) { 
    System.out.println("元素移除隨機(jī)算法:"); 
    StringBuffer buffer = new StringBuffer(); 
    List<Integer> numbers = initList(start, end); 
    for (int i = 0; i < count; i++) { 
      int random = NumberUtils.randomInteger(count - i); 
      buffer.append(i == 0 ? ("[" + numbers.get(random)) : (", " + numbers.get(random))); 
      numbers.remove(random); 
    } 
     
    buffer.append("]"); 
    System.out.println(buffer); 
  } 

第四次嘗試:狀態(tài)轉(zhuǎn)移隨機(jī)算法

在我之前的很多博客中,就有一些是算法中的狀態(tài)轉(zhuǎn)移過(guò)程。而狀態(tài)的轉(zhuǎn)移也是我最喜歡的算法之一。下面的圖-1中標(biāo)注了隨機(jī)數(shù)的取值范圍,序列中的橙色數(shù)字是結(jié)果中的隨機(jī)序列。最下方的序列中有一些虛線的箭頭,代表了狀態(tài)的轉(zhuǎn)移。

圖-1 基于狀態(tài)轉(zhuǎn)移的抽樣隨機(jī)數(shù)生成算法

實(shí)現(xiàn)代碼:

 private void statusRandom(int start, int end, int count) { 
    System.out.println("狀態(tài)轉(zhuǎn)移隨機(jī)算法:"); 
    StringBuffer buffer = new StringBuffer(); 
    int[] status = new int[end + 1]; 
    for (int i = 0; i < count; i++) { 
      int random = NumberUtils.randomInteger(start, end); 
      System.err.println(random); 
      if (status[random] == 0) { 
        buffer.append(i == 0 ? ("[" + random) : (", " + random)); 
        status[random] = random == end ? start : (random + 1); // 不可能有在start之前的數(shù)字 
      } else { 
        // 狀態(tài)轉(zhuǎn)移 
        int index = random; 
        do { 
          index = status[index]; 
        } while (status[index] != 0); 
         
        buffer.append(i == 0 ? ("[" + index) : (", " + index)); 
        status[index] = index == end ? start : (index + 1); // 不可能有在start之前的數(shù)字 
      } 
    } 
     
    buffer.append("]"); 
    System.out.println(buffer); 
  } 

第五次嘗試:遞歸Floyd隨機(jī)算法

Floyd算法說(shuō)到底也是一種狀態(tài)的轉(zhuǎn)移過(guò)程。該算法會(huì)要求輸入一個(gè)List或是array來(lái)保存已經(jīng)確定的隨機(jī)數(shù)。顧名思義,這里我會(huì)用到遞歸的解法。在遞歸的過(guò)程中,我們把第i個(gè)隨機(jī)數(shù)的狀態(tài)轉(zhuǎn)移到了第i-1個(gè)隨機(jī)身上了。代碼如下:

private List<Integer> simpleFloyd(List<Integer> list, int count, int start, int end) { 
    if (count == 0) { 
      return list; 
    } 
    list = simpleFloyd(list, count - 1, start, end - 1); 
    int random = NumberUtils.randomInteger(start, end); 
    if (list.contains(random)) { 
      list.add(end); 
    } else { 
      list.add(random); 
    } 
    return list; 
  } 

第六次嘗試:迭代Floyd隨機(jī)算法

思路與上面的遞歸Floyd隨機(jī)算法是相似的,不過(guò),這里我們加入了一個(gè)變量來(lái)做優(yōu)化。就不需要再去遞歸了。代碼如下:

private List<Integer> iterationFloyd(int start, int end, int count) { 
    System.out.println("迭代Floyd隨機(jī)算法:"); 
    List<Integer> list = new ArrayList<>(); 
    for (int i = end - count + 1; i < end; i++) { 
      int random = NumberUtils.randomInteger(start, i); 
      if (list.contains(random)) { 
        list.add(i); 
      } else { 
        list.add(random); 
      } 
    } 
     
    return list; 
  } 

測(cè)試結(jié)果:

 

圖-2 隨機(jī)數(shù)生成算法測(cè)試結(jié)果

在上面的測(cè)試結(jié)果中,我們可以很明顯地看出樸素隨機(jī)算法不僅有重復(fù)數(shù)據(jù),而且還是最耗時(shí)的。所以,在抽樣的隨機(jī)數(shù)生成時(shí),避免使用這一算法。而在后幾種算法中,狀態(tài)轉(zhuǎn)移隨機(jī)算法最佳,迭代Floyd隨機(jī)算法次之。這個(gè)可以根據(jù)個(gè)人偏愛(ài)來(lái)做選擇。

相關(guān)文章

  • java字符串拼接與性能分析詳解

    java字符串拼接與性能分析詳解

    在JAVA中拼接兩個(gè)字符串的最簡(jiǎn)便的方式就是使用操作符”+”。如果你用”+”來(lái)連接固定長(zhǎng)度的字符串,可能性能上會(huì)稍受影響,但是如果你是在循環(huán)中來(lái)”+”多個(gè)串的話,性能將指數(shù)倍的下降,下面我們分析一下JAVA字符串拼接的性能
    2014-01-01
  • 徹底解決Spring mvc中時(shí)間的轉(zhuǎn)換和序列化等問(wèn)題

    徹底解決Spring mvc中時(shí)間的轉(zhuǎn)換和序列化等問(wèn)題

    這篇文章主要介紹了徹底解決Spring mvc中時(shí)間的轉(zhuǎn)換和序列化等問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • Java數(shù)據(jù)結(jié)構(gòu)順序表的詳細(xì)講解

    Java數(shù)據(jù)結(jié)構(gòu)順序表的詳細(xì)講解

    大家好,今天給大家?guī)?lái)的是順序表,我覺(jué)得順序表還是有比較難理解的地方的,于是我就把這一塊的內(nèi)容全部整理到了一起,希望能夠給剛剛進(jìn)行學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)的人帶來(lái)一些幫助,或者是已經(jīng)學(xué)過(guò)這塊的朋友們帶來(lái)更深的理解,我們現(xiàn)在就開(kāi)始吧
    2022-05-05
  • springboot中shiro使用自定義注解屏蔽接口鑒權(quán)實(shí)現(xiàn)

    springboot中shiro使用自定義注解屏蔽接口鑒權(quán)實(shí)現(xiàn)

    本文主要介紹了springboot中shiro使用自定義注解屏蔽接口鑒權(quán)實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • vue 實(shí)現(xiàn)刪除對(duì)象的元素 delete

    vue 實(shí)現(xiàn)刪除對(duì)象的元素 delete

    這篇文章主要介紹了vue 實(shí)現(xiàn)刪除對(duì)象的元素delete,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • spring中的BeanFactory與FactoryBean的講解

    spring中的BeanFactory與FactoryBean的講解

    今天小編就為大家分享一篇關(guān)于spring中的BeanFactory與FactoryBean的講解,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-01-01
  • 詳解如何使用Jersey客戶(hù)端請(qǐng)求Spring Boot(RESTFul)服務(wù)

    詳解如何使用Jersey客戶(hù)端請(qǐng)求Spring Boot(RESTFul)服務(wù)

    本篇文章主要介紹了詳解如何使用Jersey客戶(hù)端請(qǐng)求Spring Boot(RESTFul)服務(wù),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-01-01
  • 使用Runtime 調(diào)用Process.waitfor導(dǎo)致的阻塞問(wèn)題

    使用Runtime 調(diào)用Process.waitfor導(dǎo)致的阻塞問(wèn)題

    這篇文章主要介紹了使用Runtime 調(diào)用Process.waitfor導(dǎo)致的阻塞問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java多線程并發(fā)執(zhí)行demo代碼實(shí)例

    Java多線程并發(fā)執(zhí)行demo代碼實(shí)例

    這篇文章主要介紹了Java多線程并發(fā)執(zhí)行demo代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-06-06
  • java中實(shí)現(xiàn)創(chuàng)建目錄與創(chuàng)建文件的操作實(shí)例

    java中實(shí)現(xiàn)創(chuàng)建目錄與創(chuàng)建文件的操作實(shí)例

    用Java創(chuàng)建文件或目錄非常簡(jiǎn)單,下面這篇文章主要給大家介紹了關(guān)于java中實(shí)現(xiàn)創(chuàng)建目錄與創(chuàng)建文件的操作實(shí)例,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-01-01

最新評(píng)論