数组随机排序

如何将一个数组随机排序?

这个题目很有意思,我在直播的时候看的,大家讨论如何将一个数组进行随机排序。然后我想到的是sort+Math.random()

也就是下面这样:

js 复制代码
function shuffle(array) {
  return array.sort(() => Math.random() - 0.5)
}

利用数组的sort算法,比较函数返回一个-0.5到0.5的随机数,这个方法看似可行,其实有很大的问题。

V8 sort

从v8 blogv8.dev/blog/array-...上可以看到,v8 sort现在是采用Timsort算法,TimSort算法是一种起源于归并排序和插入排序的混合排序算法;而在以前,则是采用插入排序(长度小于10时)+快排的算法.

既然怎样都跑不开插入排序,那就以插入排序为排序算法,以数组[1, 2, 3] 为样例,计算得出通过random sort后得到[1, 2, 3]的概率为25%(第一次插入得到[1, 2]概率为50%,得到[1, 2]后3直接插入队尾的概率为50%),而我们知道,真正的随机算法得到[1, 2, 3]的概率应该为1/6.

除了插入排序,其他排序算法也会有这些问题,可以在这个网站上测试你的随机排序算法:bost.ocks.org/mike/shuffl...

改进

js 复制代码
function shuffle(array) {
  const random = {}
  array.forEach(item => {
    random[item] = Math.random()
  })
  return array.sort((a, b) => {
    return random[a] - random[b]
  })
}

这样做解决了上述问题,每个数在比较时的概率不再独立。但也有缺点:会有额外的空间,时间复杂度为O(nlogn),有没有更好的方法呢?

再次改进:Fisher--Yates算法

Fisher--Yates算法是由Ronald Fisher和Frank Yates共同提出,其用js的实现如下:

js 复制代码
function shuffle(array) {
  let n = array.length;
  while (n > 0) {
    const i = Math.floor(Math.random() * n--)
    const tmp = array[i]
    array[i] = array[n]
    array[n] = tmp
  }
  return array
}

核心思想:每次从剩余的项里随机取一个项,记录并剔除该项再进入下次循环.

Fisher--Yates算法做到了不额外申请空间&O(n)的时间复杂度,可以说是最优的随机排序算法了.

再次优化一下

js 复制代码
function shuffle(array) {
  for (let i = array.length; i>= 0; i--) {
    let curIndex = Math.floor(i * Math.ramdon())
    [array[i], array[curIndex]] = [array[curIndex], array[i]]
  }
  return array
}

这样可以利用数组解构方法, 少一个中间变量, 这就是最终版本了, 还有其他更好的办法吗?欢迎大家评论区讨论一下?

相关推荐
Aaron158812 分钟前
全频段 SDR干扰源模块解决方案(星链干扰、LORA无人机干扰)
人工智能·算法·fpga开发·硬件架构·硬件工程·无人机·信息与通信
布局呆星12 分钟前
Vue Router 笔记(二):正则路由、组件通信与动态路由
前端·javascript·vue.js
AI科技星16 分钟前
全域数学·球面拓扑微扰标准系数η=0.01 应用详解(典籍正式版)
人工智能·算法·数学建模·数据挖掘·机器人
逻辑君30 分钟前
物理学研究报告【20260001】
人工智能·算法
rising start31 分钟前
InsightEdu - 轻量智能学习平台
javascript·axios·css3·html5·fastapi·orm·dify
AI科技星39 分钟前
算法联盟·全域数学公理体系下黑洞标量毛发与LVK引力波O4全维理论、求导、证明、计算、验证、分析
人工智能·线性代数·算法·架构·学习方法·量子计算
谙弆悕博士39 分钟前
【附C语言源码】C语言 栈结构 实现及其扩展操作
c语言·开发语言·数据结构·算法·链表·指针·
YuanDaima204841 分钟前
图论基础原理与题目说明
数据结构·人工智能·python·算法·图论·手撕代码
AI人工智能+电脑小能手41 分钟前
【大白话说Java面试题 第53题】【JVM篇】第13题:JVM采用什么算法判断一个对象是否需要被回收?
java·jvm·算法·面试
小赵不会秃头1 小时前
数据结构Day 06:线性结构、库操作及 Makefile 完整学习笔记
java·linux·数据结构·算法·面试