🌈【LeetCode.数组打乱】- JavaScript =>模拟

388 阅读2分钟

「这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战


说明:文章部分内容及图片出自网络,如有侵权请与我本人联系(主页有公众号:小攻城狮学前端)

作者:小只前端攻城狮、 主页:小只前端攻城狮的主页、 来源:掘金

GitHub:P-J27、 CSDN:PJ想做前端攻城狮

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。


题意描述

给你一个整数数组 nums ,设计算法来打乱一个没有重复元素的数组。

实现 Solution class:

  • Solution(int[] nums) 使用整数数组 nums 初始化对象
  • int[] reset() 重设数组到它的初始状态并返回
  • int[] shuffle() 返回数组随机打乱后的结果

示例:

输入 ["Solution", "shuffle", "reset", "shuffle"] [[[1, 2, 3]], [], [], []] 输出 [null, [3, 1, 2], [1, 2, 3], [1, 3, 2]]

解释 Solution solution = new Solution([1, 2, 3]); solution.shuffle(); 打乱数组 [1,2,3] 并返回结果。任何 [1,2,3]的排列返回的概率应该相同。例如,返回 [3, 1, 2] solution.reset(); 重设数组到它的初始状态 [1, 2, 3] 。返回 [1, 2, 3] solution.shuffle(); 随机返回数组 [1, 2, 3] 打乱后的结果。例如,返回 [1, 3, 2]

提示:

  • 1 <= nums.length <= 200
  • -106 <= nums[i] <= 106
  • nums 中的所有元素都是 唯一
  • 最多可以调用 5 * 10^4 次 reset 和 shuffle
分析

很明显题目就是一个考察我们经典的洗牌算法,思路是在前n-1张牌洗好的情况下,第n张牌随机与前n-1张牌的其中一张牌交换,或者不换,即是随机洗牌。

什么是洗牌?

  • 我们得保证每一个元素在任意一个位置上的概率是一样的
  • 最简单的想法,每次都选取一个放在第一个位置上--总共n轮
解法1:朴素版本
 let n = this.nums.length;
    let ans = new Array(n).fill(0);
    let list = [];
    this.ori.forEach(v=>list.push(v));
    const floor = Math.floor
    for(let i=0;i<n;i++) {
    let id = floor(Math.random()*list.length);
    ans[i] = list.splice(id,1); 
   }
    return ans;
解法二:洗牌算法
 let n = this.ori.length;
    let ans = this.ori.slice();
    const floor = Math.floor;
    for(let i=0;i<n;i++) {
     let k = floor(Math.random() * (n-i)) + i;
  [ans[i],ans[k]] = [ans[k],ans[i]];
 }
    return ans;

最后:其实我们可以因为替换与不替换只有两种选择,概率都是50%,而随机数小于0.5 和 大于等于0.5 的概率 分别是 50%,因此可以根据随机数的大小,判断是否需要替换,通过对每一对索引值进行随机判断,从而达到随机打乱数组的目的、


感谢阅读,希望能对你有所帮助,文章若有错误或者侵权,可以在评论区留言或在我的主页添加公众号联系我。

写作不易,如果觉得不错,可以「点赞」+「评论」 谢谢支持❤