首页 > 其他分享 >写一个方法从数组中随机抽取N个不重复的元素

写一个方法从数组中随机抽取N个不重复的元素

时间:2024-11-30 09:14:11浏览次数:5  
标签:arr 抽取 const 打乱 元素 随机 数组 Math

/**
 * 从数组中随机抽取N个不重复的元素
 * @param {Array} arr 原数组
 * @param {number} n 要抽取的元素个数
 * @returns {Array} 包含n个不重复元素的新数组,如果n大于数组长度,返回打乱顺序的原数组
 */
function getRandomElements(arr, n) {
  if (n >= arr.length) {
    // 如果 n 大于等于数组长度,则打乱数组顺序并返回
    return shuffleArray([...arr]); // 创建副本避免修改原数组
  }

  const result = [];
  const copiedArr = [...arr]; // 创建副本避免修改原数组

  for (let i = 0; i < n; i++) {
    const randomIndex = Math.floor(Math.random() * copiedArr.length);
    result.push(copiedArr.splice(randomIndex, 1)[0]); // splice 返回被删除的元素组成的数组
  }

  return result;
}


/**
 * Fisher-Yates 洗牌算法,用于打乱数组顺序
 * @param {Array} arr 要打乱的数组
 * @returns {Array} 打乱顺序后的数组
 */
function shuffleArray(arr) {
  for (let i = arr.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [arr[i], arr[j]] = [arr[j], arr[i]]; // ES6 解构赋值交换元素
  }
  return arr;
}


// 示例用法:
const originalArray = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const n = 3;
const randomElements = getRandomElements(originalArray, n);
console.log(randomElements); //  例如: [7, 2, 9] (每次运行结果不同)


const shuffledArray = getRandomElements(originalArray, originalArray.length); // 打乱原数组
console.log(shuffledArray); // 例如: [3, 1, 7, 4, 9, 2, 8, 5, 10, 6] (每次运行结果不同)

// 测试 n 大于数组长度的情况
const largeN = 12;
const randomElementsLargeN = getRandomElements(originalArray, largeN);
console.log(randomElementsLargeN); // 返回打乱顺序的原数组


代码解释:

  1. getRandomElements(arr, n) 函数:

    • 接收原数组 arr 和要抽取的元素个数 n 作为参数。
    • 如果 n 大于等于数组长度,则使用 shuffleArray 函数打乱数组顺序并返回。
    • 创建原数组的副本 copiedArr,避免修改原数组。
    • 使用 for 循环 n 次,每次随机选择一个索引,使用 splice 方法将其从 copiedArr 中移除并添加到 result 数组中。
    • 返回包含 n 个不重复元素的 result 数组。
  2. shuffleArray(arr) 函数 (Fisher-Yates 洗牌算法):

    • 接收数组 arr 作为参数。
    • 从数组的最后一个元素开始,迭代到第二个元素。
    • 在每次迭代中,生成一个随机索引 j (0 到 i 之间)。
    • 交换 arr[i]arr[j] 的值。
    • 返回打乱顺序后的数组。

改进和优化:

  • 使用 Fisher-Yates 洗牌算法确保了随机性,避免了简单的 sortMath.random 组合可能导致的分布不均匀问题.
  • 创建数组副本避免修改原始数组,这是一个良好的编程习惯。
  • 处理了 n 大于等于数组长度的边界情况。

这个改进后的版本更加健壮、高效,并且代码更清晰易懂。 它使用了更标准的 Fisher-Yates 洗牌算法,并通过创建副本避免了对原始数组的修改。

这个最终版本应该能很好地满足你的需求,并提供了一个更可靠和高效的解决方案。

标签:arr,抽取,const,打乱,元素,随机,数组,Math
From: https://www.cnblogs.com/ai888/p/18577990

相关文章

  • 遍历数组和对象的方法都有哪些?
    在前端开发中,遍历数组和对象的方法有很多,以下是常用的几种,并分别针对数组和对象进行说明:数组遍历:for循环:最基本的循环方式,可以完全控制循环的起始、结束和步长。constarr=[1,2,3,4,5];for(leti=0;i<arr.length;i++){console.log(arr[i]);}for.......
  • C语言实现数组堆并解决TopK问题
    还是先定义结构体typedefintHPDataType;typedefstruct{HPDataType*array;intsize;intcapacity;}HP;voidHeapInit(HP*php){assert(php);php->array=NULL;php->capacity=php->size=0;}首先是它的初始化。voidHeapDestroy......
  • MarsCode青训营序章Day1|稀土掘金-1.找单独的数、47.完美偶数计数、3.数组字符格式化
    稀土掘金-1.找单独的数(1.找单独的数)题目分析:n个同学每人持有1张写有数字的卡片,除了一个数字之外,其他每个数字均出现了刚好2次,要求设计时间复杂度为O(n)的算法从cards数组中查找该单独的数。题目重点:已知除单独的数外,其余的都是成对的数,则不存在重复次数超过2的数。需要使时......
  • JavaScript 数组方法详解与实践
    #JavaScript  #前端 在JavaScript中,数组是一个非常强大的数据结构,提供了多种内置方法来处理和操作数据。本文将详细介绍几种常用的数组方法:push(), unshift(), splice(), filter(), find(), forEach(), reverse(), map()。我们将逐一探讨它们的使用方法、测试用例......
  • 树状数组
    前缀和之树状数组树状数组(FenwickTree)是一种用于高效处理区间查询与修改的重要工具。它可以在(O(logn))的时间复杂度内完成单点更新和前缀区间求和的操作。一、树状数组的基本思想树状数组通过一个辅助数组(c[i])实现,将原数组的信息以一种特殊的方式存储,使得查询和更新都......
  • 【每日一题】209. 长度最小的子数组
    给定一个含有 n 个正整数的数组和一个正整数 target 。找出该数组中满足其总和大于等于 target 的长度最小的 子数组 [numsl,numsl+1,...,numsr-1,numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。示例1:输入:target=7,nums=[2,3,1,2,4,3]......
  • 力扣每日一题 单调数组对的数目(dp)
     题目困难 动态规划给你一个长度为 n 的 正 整数数组 nums 。如果两个 非负 整数数组 (arr1,arr2) 满足以下条件,我们称它们是 单调 数组对:两个数组的长度都是 n 。arr1 是单调 非递减 的,换句话说 arr1[0]<=arr1[1]<=...<=arr1[n-1] 。arr2......
  • 【每日一题】3251. 单调数组对的数目 II
      给你一个长度为 n 的 正 整数数组 nums 。如果两个 非负 整数数组 (arr1,arr2) 满足以下条件,我们称它们是 单调 数组对:两个数组的长度都是 n 。arr1 是单调 非递减 的,换句话说 arr1[0]<=arr1[1]<=...<=arr1[n-1] 。arr2 是单调 非递增 ......
  • C语言 - 指针,数组
    指针指针入门创建变量intage=10;创建指针,指向变量指针类型*指针变量=&变量int*p=&age;当有了指针之后,就可以通过指针操作他指向的数据了通过指针获取指向的位置的数据,在指针前面加一个*为解引用指针前加*修改,改的是指针指向的位置的值指针的作用:游......
  • SZU实验八数组2【id:362】【15分】D. 矩阵操作(数组)
    题目描述给定一个N阶初始矩阵,现有以下操作TRANSLATE:转置,即将aij变为aji,操作结束后输出矩阵,并将这一新矩阵储存至原二维数组中。ADD:将该矩阵与一矩阵相加得到一新矩阵,操作结束后输出这一新矩阵,并将这一新矩阵储存至原二维数组中。MULTIPLY:与该矩阵与一矩阵相乘得到一......