1 題目
給定一個從0到N的閉區間,隨機地輸出該區間內的整數,每個整數出現且僅出現一次。
2 思路1
直接通過內置的隨機函數,每次隨機出一個值,然後放入到列表中
package main
import (
"fmt"
"math/rand"
"time"
)
func getRandIntList(length int) []int {
var intList []int
numberExistMap := map[int]bool{}
rand.Seed(time.Now().Unix())
for true {
// 返回[0, length)內的隨機值
randNumber := rand.Intn(length)
if _, ok := numberExistMap[randNumber]; ok {
continue
}
numberExistMap[randNumber] = true
intList = append(intList, randNumber)
if len(intList) == length {
break
}
}
return intList
}
func main() {
intList := getRandIntList(10)
fmt.Println(fmt.Sprintf("intList:%+v with length:%d", intList, len(intList)))
}
輸出:
intList:[3 4 2 7 8 1 9 5 6 0] with length:10
這種方法其實並沒有滿足每個數字只出現一次的要求。
3 思路2 - 素數取模隨機法
- 對於一個數組[n]int,隨機的從小於n的素數集合中,選擇一個素數,假定是p;
- 從數組[0, n-1]中隨機選擇一個數開始,假定是m;
- 隨機出來的第一個值爲
(m + p) % n = i
,第二次值爲(上一個值 + p) % n
,也就是(i+p) % n
,以此類推,就產生了n個數,;
舉例:對於[1, 8]的區間,其素數集合是{1, 3, 5, 7},假定選擇的素數是5,從1開始。
訪問輪次 | 取模值 | 所需值 |
1 | (1 + 5)%8 = 6 | 6 + 1 = 7 |
2 | (6 + 5)%8 = 3 | 3 + 1 = 4 |
3 | (3 + 5)%8 = 0 | 0 + 1 = 1 |
4 | (0 + 5)%8 = 5 | 5 + 1 = 6 |
5 | (5 + 5)%8 = 2 | 2 + 1 = 3 |
6 | (2 + 5)%8 = 7 | 7 + 1 = 8 |
7 | (7 + 5)%8 = 4 | 4 + 1 = 5 |
8 | (4 + 5)%8 = 1 | 1 + 1 = 2 |
從上面例子可以看出,執行8次即可產生全部的元素,而且由於素數和開始的數是隨機的,那麼結果也能做到隨機性。