汉明数生成代码异常求助:无法正确获取前10个汉明数
汉明数生成代码的问题分析与修复方案
咱们来一步步拆解你代码里的问题,先从getFactors函数说起,再看hammingNums的逻辑漏洞:
一、getFactors函数的核心问题
1. 全局变量污染是最大的坑
你定义的factors、isPrime、i都是全局变量,每次调用getFactors时,这些变量不会自动重置,会保留上一次调用的结果。比如第一次调用getFactors(4)后,factors里存了[2,2],第二次调用getFactors(3)时,会继续往这个数组里加3,导致返回的质因数集合完全错误。
2. 质因数分解的逻辑漏洞
- 循环条件
i < num效率极低且有隐患:比如判断num=25时,i要从3一直跑到5才会找到因数,改成i <= Math.sqrt(num)能大幅减少循环次数; - 递归的处理不够严谨:找到一个因数后直接push然后递归,但没有持续分解剩余的数值,不过这个问题在全局变量的影响下被放大了。
二、hammingNums函数的逻辑错误
1. 汉明数的判断逻辑完全错了
(getFactors(i)).has(2 && 3 && 5)这个写法在JS里会被解析成判断集合里是否有5(因为2 && 3 &&5的结果是最后一个真值5),而不是判断所有质因数都只能是2、3、5(包括1这种没有质因数的情况)。
2. 循环逻辑混乱
你用while(list.length <11)嵌套for(i=1; i<1000; i++),每次while循环都会把1到1000里的符合条件的数重新push一遍,导致list里会有大量重复元素,而且完全不是按从小到大的顺序收集前10个汉明数。
3. 全局变量i导致循环异常
hammingNums里的i没有用let声明,属于全局变量,会和getFactors里的i互相干扰,导致循环索引混乱。
三、修正后的代码示例
先修复getFactors,把变量改成局部的,优化分解逻辑:
function getFactors(num) { const factors = []; // 先处理所有2的因数 while (num % 2 === 0) { factors.push(2); num /= 2; } // 处理奇数因数,从3开始每次加2,减少循环次数 for (let i = 3; i <= Math.sqrt(num); i += 2) { while (num % i === 0) { factors.push(i); num /= i; } } // 如果剩下的num是大于2的质数,直接加入 if (num > 2) { factors.push(num); } return new Set(factors); }
然后修复hammingNums,正确判断汉明数,按顺序收集前10个:
function hammingNums() { const list = []; let num = 1; // 收集前10个汉明数,所以长度小于10时继续循环 while (list.length < 10) { const primeFactors = getFactors(num); // 判断所有质因数都是2、3、5,或者没有质因数(对应num=1) const isHamming = [...primeFactors].every(factor => [2, 3, 5].includes(factor)); if (isHamming) { list.push(num); } num++; } return list; } // 测试调用 console.log(hammingNums()); // 输出:[1, 2, 3, 4, 5, 6, 8, 9, 10, 12]
额外优化:更高效的汉明数生成法
如果需要生成大量汉明数,逐个判断质因数的效率太低,可以用动态规划的方法,通过乘以2、3、5来生成,避免重复计算:
function hammingNumsOptimized() { const hamming = [1]; let i2 = 0, i3 = 0, i5 = 0; while (hamming.length < 10) { const next2 = hamming[i2] * 2; const next3 = hamming[i3] * 3; const next5 = hamming[i5] * 5; const nextMin = Math.min(next2, next3, next5); hamming.push(nextMin); // 避免重复生成相同的数,对应索引自增 if (nextMin === next2) i2++; if (nextMin === next3) i3++; if (nextMin === next5) i5++; } return hamming; }
内容的提问来源于stack exchange,提问作者Chi Lee
相关产品推荐
相关产品推荐

