生成指定範圍和個數的不重複的隨機整數

生成指定範圍內的隨機數,有相應的隨機函數(如RandomRange(x, y)可生成x <= d < y的隨機整數),或者在基本的隨機函數上稍加修改也可生成;生成 n 個隨機數,只需調用 n 次隨機函數便可;生成 n 個不重複的隨機數,就會有一點點小麻煩。算法

常規思路

通常來講,要生成n個不重複的隨機數,只需判斷每次生成的隨機數有沒有和這前生成的隨機數重複便可,若重複即拋棄,不重複則記錄。數組

可是,這樣要進行不少額外的判斷,並且當生成的量變大時,這樣的判斷次數也幾乎是呈指數級的增長(具體複雜度沒有進行詳細分析)。dom

另外一種思路

若是每生成一個隨機整數,就在一個整數序列上對應的位置作一個標記,那麼只須要判斷標記的個數有沒有達到n便可,而後把有標記的整數取出就是 n 個不重複的隨機整數。(其實該思路是借鑑了某個排序算法的思路,具體算法名稱不記得了函數

首先來考慮生成 n 個[0, m)的不重複的隨機數方法,n < mcode

var
  i: Integer;
  tmpMark: array of Integer;
begin
  SetLength(tmpMark, m);
  repeat
    Randomize;
    i := RandomRange(0, m); //[0,m)半開半閉區間
    tmpMark[i] := 1;
  until SumInt(tmpMark) = n;
  for i := 0 to m - 1 do
    if tmpMark[i] = 1 then
      i; //i即爲隨機出的不重複的整數
end;

本例中借滋長度爲m的數組tmpMark來進行標記,同時使用delphi自帶的SumInt(在Math單元)函數來計算標記的個數,有標記的tmpMark下標即爲隨機出的整數。排序

對於[x, y)區間,能夠在[0, m)的基礎上進行平移來實現,n < y - xclass

var
  l, i: Integer;
  tmpMark: array of Integer;
begin
  l := y - x;
  SetLength(tmpMark, l);
  repeat
    Randomize;
    i := RandomRange(x, y); //[x,y)半開半閉區間
    tmpMark[i - x] := 1;
  until SumInt(tmpMark) = n;
  for i := 0 to l - 1 do
    if tmpMark[i] = 1 then
      i + x; //i+x即爲隨機出的不重複的整數
end;
相關文章
相關標籤/搜索