1.3.8 随机打乱数组

  1. 把数组随机打乱的实质就是”洗牌问题“,”洗牌问题“不仅仅追求速度,还要求足够乱

  2. 这里通过Fisher-Yates随机置乱算法来进行讲解

  3. Fisher-Yates随机置乱算法也称为高纳德置乱算法,其核心思想是兄1n之间随机出一个数和最后一个数(n)交换,然后从1n-1之间随机出一个数和倒数第二个数(n-1)交换,这个算法生成的随机排列是等概率的,所以每个排列都是等可能的,示例如下:

    func init() {
    	rand.Seed(time.Now().Unix())
    }
    
    // RandomInt Fisher-Yates随机置乱算法生成随机整数
    func RandomInt(strings []string, length int) (string, error) {
    	if len(strings) <= 0 {
    		return "", errors.New("字符串长度不能小于0")
    	}
    
    	if length <= 0 || len(strings) <= length {
    		return "", errors.New("参数长度非法")
    	}
    
    	for i := len(strings) - 1; i > 0; i-- {
    		num := rand.Intn(i + 1)
    		strings[i], strings[num] = strings[num], strings[i]
    	}
    	str := ""
    	for i := 0; i < length; i++ {
    		str += strings[i]
    	}
    	return str, nil
    }
    
    func main() {
    	str := []string{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}
    	a, _ := RandomInt(str, 9)
    	fmt.Println(a)
    }
  4. 注意:无论是算法本身的执行过程,还是生成随机数的过程,使用Fisher-Yates随机置乱算法必须谨慎,否则就可能出现一些偏差。例如随机数生成带来的误差,会造成洗牌的结果整体上不满足均匀分布的特点

Last updated