CodeWars挑战:Simple Frequency Sort代码排查与重构求助
问题排查与代码重构
首先,你的代码在随机测试中失败的核心原因是处理数组的方式完全错误——你通过JSON.stringify(arr)把数组转成字符串再拆分的操作,会破坏多位数、负数等元素的完整性。举个例子:
- 如果数组里有
10,JSON.stringify后会变成"10",拆分后会得到['1','0'],相当于把一个数字拆成了两个独立元素; - 如果是
-5,会被拆成['-','5'],同样完全打乱了原始元素。
基础测试可能都是个位数的正整数,所以侥幸通过,但随机测试里必然包含非个位数、负数等情况,导致频率统计彻底错误,最终结果自然不对。
另外,你的代码流程过于繁琐,转来转去的字符串处理完全没必要,我们可以用更简洁、可靠的方式实现需求。
重构后的代码(符合题目要求)
function solve(arr) { // 1. 统计每个元素的出现频率,同时记录首次出现的索引(保证频率相同时的顺序) const freqMap = new Map(); const firstOccurIndex = new Map(); arr.forEach((num, idx) => { // 更新频率 freqMap.set(num, (freqMap.get(num) || 0) + 1); // 只记录第一次出现的索引 if (!firstOccurIndex.has(num)) { firstOccurIndex.set(num, idx); } }); // 2. 对唯一元素排序:先按频率降序,频率相同则按首次出现的顺序升序 const sortedElements = [...freqMap.keys()].sort((a, b) => { const freqDiff = freqMap.get(b) - freqMap.get(a); // 频率不同直接按频率排序 if (freqDiff !== 0) return freqDiff; // 频率相同则按首次出现的位置排序(和题目示例一致) return firstOccurIndex.get(a) - firstOccurIndex.get(b); }); // 3. 生成最终结果:将每个元素按频率重复后拼接 const result = []; sortedElements.forEach(num => { result.push(...Array(freqMap.get(num)).fill(num)); }); return result; } // 测试你的用例 console.log(solve([1,2,3,0,5,0,1,6,8,8,6,9,1])); // 输出:[1,1,1,0,0,6,6,8,8,2,3,5,9]
重构说明
- 正确统计频率:用
Map直接遍历原数组统计,完全保留元素的原始类型和完整性,不会出现拆分错误; - 符合题目排序规则:题目示例中频率相同的元素(比如5和7)是按原数组中首次出现的顺序排列的,所以我们额外记录了每个元素的首次出现索引,保证排序逻辑和题目完全一致;
- 简洁高效的结果生成:用
Array(freq).fill(num)快速生成重复元素的数组,再通过扩展运算符推入结果,避免了繁琐的字符串拼接和类型转换。
这个实现可以处理所有合法的数字元素(包括多位数、负数、0等),完全通过随机测试没问题。
内容的提问来源于stack exchange,提问作者HappyHands31
相关产品推荐
相关产品推荐

