JavaScript乘法表指定范围带条件随机数生成问题及实现方案
JavaScript乘法表随机组合生成实现方案
需求说明
需实现乘法表场景下的带条件随机数生成功能,为2-10的每个乘数生成对应随机被乘数组合,满足指定约束规则。
现有运行问题
- 生成的数组中存在重复的乘法组合,例如多次出现
2×4的条目 - 每次生成的数组长度不固定
- 存在乘积重复问题,若同时存在
4×7和7×4这类乘积相同的条目,需要替换其中一组为新的符合条件的组合 - 各乘数的条目生成需满足指定频次规则,例如乘数9的条目最少生成1条,最多不超过3条
预期实现效果
- 每个乘数对应的组合唯一无重复
- 每次生成的数组长度固定为18
- 自动校验乘积唯一性,若新增组合的乘积已在数组中存在则重新生成,且仍符合各乘数的频次约束
问题根因
原有代码存在以下缺陷:
- 重复校验逻辑失效:用
indexOf判断对象数组中的数值是否存在,对象比对永远返回-1,没有实现任何去重逻辑 - 未校验乘积唯一性:只做了基础的被乘数判断,没有校验乘积重复场景
- 频次总和无约束:随机生成的各乘数频次总和不固定,直接导致最终数组长度不稳定
- 重复场景直接跳过:随机到重复值时没有重试补充,进一步导致数组长度不足
修改后完整代码
const randomNumbersGenerator = () => { // 随机整数生成工具 function getRandomInt(min, max) { min = Math.ceil(min); max = Math.floor(max); return Math.floor(Math.random() * (max - min + 1) + min); } // 乘数配置:乘数数值、最小生成条数、最大生成条数 const multiplierConfigs = [ { val: 2, min: 0, max: 2 }, { val: 3, min: 0, max: 3 }, { val: 4, min: 0, max: 3 }, { val: 5, min: 0, max: 3 }, { val: 6, min: 1, max: 3 }, { val: 7, min: 1, max: 3 }, { val: 8, min: 1, max: 3 }, { val: 9, min: 1, max: 3 }, { val: 10, min: 0, max: 2 }, ]; const TOTAL_COUNT = 18; const MULTIPLICAND_RANGE = [2, 12]; // 第一步:生成符合总长度要求的各乘数频次 // 先填充最小生成条数 const freqMap = {}; let usedCount = 0; multiplierConfigs.forEach(config => { freqMap[config.val] = config.min; usedCount += config.min; }); // 剩余配额随机分配给还有额度的乘数 while (usedCount < TOTAL_COUNT) { const randomConfig = multiplierConfigs[getRandomInt(0, multiplierConfigs.length - 1)]; if (freqMap[randomConfig.val] < randomConfig.max) { freqMap[randomConfig.val] += 1; usedCount += 1; } } // 第二步:生成符合去重要求的组合 const result = []; // 用Set做去重校验,分别存组合标识、乘积 const existedCombos = new Set(); const existedProducts = new Set(); for (const config of multiplierConfigs) { const multiplier = config.val; const count = freqMap[multiplier]; for (let i = 0; i < count; i++) { let multiplicand, product, comboKey; // 重试直到生成符合要求的被乘数 do { multiplicand = getRandomInt(MULTIPLICAND_RANGE[0], MULTIPLICAND_RANGE[1]); product = multiplier * multiplicand; comboKey = `${multiplier}x${multiplicand}`; } while (existedCombos.has(comboKey) || existedProducts.has(product)); // 存入结果和去重集合 existedCombos.add(comboKey); existedProducts.add(product); result.push({ multiplier, generated: multiplicand, product }); } } return result; }; // 测试调用 console.log(randomNumbersGenerator());
实现说明
- 先按约束生成各乘数的生成频次,确保总和固定为18,同时满足每个乘数的最小/最大条数要求
- 用两个Set分别存储已生成的组合标识和乘积,实现O(1)效率的重复校验
- 生成组合时如果遇到重复的组合或乘积,自动重试直到生成符合要求的条目,保证不会因为重复跳过导致长度不足
- 移除了原有代码中多余的乘数11相关逻辑,符合2-10的乘数范围要求
内容的提问来源于stack exchange,提问作者Brew WebDev
相关产品推荐
相关产品推荐

