Fisher-Yates洗牌算法讲解(JS版本)

2024-08-24 23:04

本文主要是介绍Fisher-Yates洗牌算法讲解(JS版本),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

什么是洗牌算法?

洗牌算法是一种将一组数据(通常是数组)打乱顺序的算法,使得所有可能的排列组合都是等概率的。这个过程类似于我们在现实中洗扑克牌的过程:你希望打乱扑克牌,使其顺序完全随机。

Fisher-Yates 洗牌算法概述

Fisher-Yates 洗牌算法是最常用的洗牌算法之一,它能够在 O(n) 的时间内完成洗牌,并且确保每个可能的排列都具有相同的概率。该算法的基本思路是从数组的最后一个元素开始,依次将其与前面任意一个随机选中的元素交换位置。

Fisher-Yates 洗牌算法的步骤

  1. 从数组的最后一个元素开始

    • 选择一个范围从 0 到当前索引的随机索引 j
    • 将当前元素与索引 j 处的元素进行交换。
    • 将范围缩小,重复上述步骤,直到处理完所有元素。
  2. 核心思想

    • 每次从未洗牌的部分中随机选择一个元素进行交换,从而保证每个元素都有机会出现在数组的任意位置。

JavaScript 实现 Fisher-Yates 洗牌算法

以下是 Fisher-Yates 洗牌算法的 JavaScript 实现:

function fisherYatesShuffle(array) {// 从最后一个元素开始遍历数组for (let i = array.length - 1; i > 0; i--) {// 生成一个 0 到 i 之间的随机整数 jconst j = Math.floor(Math.random() * (i + 1));// 交换元素 array[i] 和 array[j][array[i], array[j]] = [array[j], array[i]];}return array; // 返回打乱后的数组
}// 示例使用
let arr = [1, 2, 3, 4, 5];
console.log("Original array:", arr);let shuffledArray = fisherYatesShuffle(arr);
console.log("Shuffled array:", shuffledArray);

代码解释:

  1. for (let i = array.length - 1; i > 0; i--):

    • 我们从数组的最后一个元素开始,依次向前遍历。
  2. const j = Math.floor(Math.random() * (i + 1));:

    • Math.random() 生成一个 0 到 1 之间的随机小数。
    • 乘以 i + 1 可以将这个随机数放大到 0i 之间,然后通过 Math.floor 取整,得到 0i 之间的随机整数 j
  3. 交换操作

    • array[i]array[j] 进行交换,确保 array[i] 被随机选中的元素替换。
  4. return array:

    • 返回已经打乱顺序的数组。

运行示例:

let arr = [1, 2, 3, 4, 5];
let shuffledArray = fisherYatesShuffle(arr);
console.log(shuffledArray); // 输出一个随机打乱的数组,例如 [3, 5, 1, 2, 4]

Fisher-Yates 洗牌算法的特点

  1. 效率: 该算法的时间复杂度为 O(n),因为它仅需要一次遍历数组,并且每次遍历中只进行常数时间的操作。

  2. 公平性: 每个元素被放置在任意位置的概率都是均等的,确保了所有可能的排列组合都具有相同的概率。

  3. 空间复杂度: 该算法在原数组上进行操作,因此它的空间复杂度是 O(1),即不需要额外的空间来存储中间结果。

Fisher-Yates 洗牌算法的应用

  1. 随机排序数据: 在需要随机排序的场合(如卡牌游戏、抽奖、测验题目等),Fisher-Yates 洗牌算法是非常理想的选择。

  2. 抽样: 在数据科学和统计分析中,Fisher-Yates 洗牌可以用于生成数据的随机样本。

  3. 随机选择: 需要从大量元素中随机选择一些元素时,也可以使用该算法。

  4. 蒙特卡罗模拟: 在随机模拟和蒙特卡罗方法中,Fisher-Yates 洗牌算法可以用于生成初始的随机排列。

这篇关于Fisher-Yates洗牌算法讲解(JS版本)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1103858

相关文章

Python版本与package版本兼容性检查方法总结

《Python版本与package版本兼容性检查方法总结》:本文主要介绍Python版本与package版本兼容性检查方法的相关资料,文中提供四种检查方法,分别是pip查询、conda管理、PyP... 目录引言为什么会出现兼容性问题方法一:用 pip 官方命令查询可用版本方法二:conda 管理包环境方法

深入理解Mysql OnlineDDL的算法

《深入理解MysqlOnlineDDL的算法》本文主要介绍了讲解MysqlOnlineDDL的算法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小... 目录一、Online DDL 是什么?二、Online DDL 的三种主要算法2.1COPY(复制法)

JS纯前端实现浏览器语音播报、朗读功能的完整代码

《JS纯前端实现浏览器语音播报、朗读功能的完整代码》在现代互联网的发展中,语音技术正逐渐成为改变用户体验的重要一环,下面:本文主要介绍JS纯前端实现浏览器语音播报、朗读功能的相关资料,文中通过代码... 目录一、朗读单条文本:① 语音自选参数,按钮控制语音:② 效果图:二、朗读多条文本:① 语音有默认值:②

在Node.js中使用.env文件管理环境变量的全过程

《在Node.js中使用.env文件管理环境变量的全过程》Node.js应用程序通常依赖于环境变量来管理敏感信息或配置设置,.env文件已经成为一种流行的本地管理这些变量的方法,本文将探讨.env文件... 目录引言为什么使php用 .env 文件 ?如何在 Node.js 中使用 .env 文件最佳实践引

使用Node.js和PostgreSQL构建数据库应用

《使用Node.js和PostgreSQL构建数据库应用》PostgreSQL是一个功能强大的开源关系型数据库,而Node.js是构建高效网络应用的理想平台,结合这两个技术,我们可以创建出色的数据驱动... 目录初始化项目与安装依赖建立数据库连接执行CRUD操作查询数据插入数据更新数据删除数据完整示例与最佳

Java中实现对象的拷贝案例讲解

《Java中实现对象的拷贝案例讲解》Java对象拷贝分为浅拷贝(复制值及引用地址)和深拷贝(递归复制所有引用对象),常用方法包括Object.clone()、序列化及JSON转换,需处理循环引用问题,... 目录对象的拷贝简介浅拷贝和深拷贝浅拷贝深拷贝深拷贝和循环引用总结对象的拷贝简介对象的拷贝,把一个

Python一次性将指定版本所有包上传PyPI镜像解决方案

《Python一次性将指定版本所有包上传PyPI镜像解决方案》本文主要介绍了一个安全、完整、可离线部署的解决方案,用于一次性准备指定Python版本的所有包,然后导出到内网环境,感兴趣的小伙伴可以跟随... 目录为什么需要这个方案完整解决方案1. 项目目录结构2. 创建智能下载脚本3. 创建包清单生成脚本4

Three.js构建一个 3D 商品展示空间完整实战项目

《Three.js构建一个3D商品展示空间完整实战项目》Three.js是一个强大的JavaScript库,专用于在Web浏览器中创建3D图形,:本文主要介绍Three.js构建一个3D商品展... 目录引言项目核心技术1. 项目架构与资源组织2. 多模型切换、交互热点绑定3. 移动端适配与帧率优化4. 可

Ubuntu如何升级Python版本

《Ubuntu如何升级Python版本》Ubuntu22.04Docker中,安装Python3.11后,使用update-alternatives设置为默认版本,最后用python3-V验证... 目China编程录问题描述前提环境解决方法总结问题描述Ubuntu22.04系统自带python3.10,想升级

Unity新手入门学习殿堂级知识详细讲解(图文)

《Unity新手入门学习殿堂级知识详细讲解(图文)》Unity是一款跨平台游戏引擎,支持2D/3D及VR/AR开发,核心功能模块包括图形、音频、物理等,通过可视化编辑器与脚本扩展实现开发,项目结构含A... 目录入门概述什么是 UnityUnity引擎基础认知编辑器核心操作Unity 编辑器项目模式分类工程