前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >打乱数组

打乱数组

作者头像
木子星兮
发布2020-07-17 10:30:55
1.7K0
发布2020-07-17 10:30:55
举报
文章被收录于专栏:前端小码农前端小码农

JavaScript实现LeetCode第384题:打乱数组

题目描述

打乱一个没有重复元素的数组。

示例:

代码语言:javascript
复制
// 以数字集合 1, 2 和 3 初始化数组。
int[] nums = {1,2,3};
Solution solution = new Solution(nums);

// 打乱数组 [1,2,3] 并返回结果。任何 [1,2,3]的排列返回的概率应该相同。
solution.shuffle();

// 重设数组到它的初始状态[1,2,3]。
solution.reset();

// 随机返回数组[1,2,3]打乱后的结果。
solution.shuffle();

思路

洗牌算法:从最后一个元素开始,从数组中随机选出一个位置,交换,直到第一个元素。

leetcode

代码语言:javascript
复制
/**
 * @param {number[]} nums
 */
var Solution = function(nums) {
    this.originNums = [...nums];
    this.shuffleNums = [...nums];
};

/**
 * Resets the array to its original configuration and return it.
 * @return {number[]}
 */
Solution.prototype.reset = function() {
    return this.originNums;
};

/**
 * Returns a random shuffling of the array.
 * @return {number[]}
 */
Solution.prototype.shuffle = function() {
    const { shuffleNums } = this;
    let current = shuffleNums.length - 1;
    while(current > -1) {
        // 生成一个范围在当前下标到数组末尾元素下标之间的随机整数
        const random = Math.floor(shuffleNums.length * Math.random());
        // 将当前元素和随机选出的下标所指的元素互相交换 
        [shuffleNums[current], shuffleNums[random]] = [shuffleNums[random], shuffleNums[current]];
        current--;
    }
    return shuffleNums;
};

/**
 * Your Solution object will be instantiated and called as such:
 * var obj = new Solution(nums)
 * var param_1 = obj.reset()
 * var param_2 = obj.shuffle()
 */
  • 时间复杂度:O(n)。Fisher-Yates 洗牌算法时间复杂度是线性的,因为算法中生成随机序列,交换两个元素这两种操作都是常数时间复杂度的。
  • 空间复杂度:O(n)。因为要实现 重置,原始数组必须得保存一份。

拓展题目

实现随机抽奖程序 接受一个数组 arr, n , 从数组中抽出n个人

思路一:

按照我们正常的抽奖的最简单做法,一般是把工号写到一个球上面,摇 n 次,然后每次摇出1个号,该号码即为中奖号码,同时将该球拿出去,重复 n 次。

代码语言:javascript
复制
function lottery(arr, n) {
    const result = [];
    let i = 0;
    while( i < n) {
        // 每次从数组中随机抽出一个值,使用 slice将该值从原数组数组中删除,将该值添加到 result中
        const value = arr.splice(Math.floor(Math.random() * arr.length), 1)
        result.push(value[0]);
        i++;
    }
    return result;
}
思路二:

还有一种思路是将数组打乱,直接截取 前 n 个数。就是著名的 洗牌算法。

打乱数组(洗牌算法):从最后一个元素开始,从数组中随机选出一个位置,交换,直到第一个元素。

代码语言:javascript
复制
function disorder(array) {
    const length = array.length;
    let current = length - 1;
    while(current > -1) {
        const random = Math.floor(length * Math.random());
        // 数组的每个值都会和另外一个随机位置的值交换位置
        // 使用数组的解构赋值,交换数组中的两个元素的位置
        [ array[current], array[random] ] = [ array[random], array[current] ];
        current--;
    }
    return array;
}

const result = disorder(arr);
result.slice(0, n)

推荐阅读

  • 神一样的随机算法
  • JS中随机排列数组顺序(经典洗牌算法)和数组的排序方法[1]
  • leetcode官方题解[2]

参考资料

[1]

JS中随机排列数组顺序(经典洗牌算法)和数组的排序方法: https://zhuanlan.zhihu.com/p/27589512

[2]

leetcode官方题解: https://leetcode-cn.com/problems/shuffle-an-array/solution/da-luan-shu-zu-by-leetcode/

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-04-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 牧码的星星 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 题目描述
  • 思路
  • 拓展题目
    • 实现随机抽奖程序 接受一个数组 arr, n , 从数组中抽出n个人
      • 思路一:
      • 思路二:
  • 推荐阅读
    • 参考资料
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档