You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何优化双字符数组共通元素保留及删除次数统计的冗余代码?

嘿,我来帮你搞定这个代码优化的问题,顺便把你不熟悉的reduce和map用法讲明白~

优化思路与代码实现

首先明确核心需求:要让两个字符数组元素一致,需要删除的总次数 = 两个数组的总长度 - 2 × 两个数组的公共元素总数(每个公共元素在两边都不用删,剩下的都要删掉)。

第一步:解决基础场景(无重复元素)

如果数组里没有重复元素,我们可以用filter快速找出公共元素,再计算结果:

function countDeletions(arr1, arr2) {
  // 筛选出arr1中同时存在于arr2的元素
  const commonElements = arr1.filter(item => arr2.includes(item));
  // 总删除次数 = 总长度 - 2倍公共元素数
  return arr1.length + arr2.length - 2 * commonElements.length;
}

测试示例:countDeletions(["a","b"], ["a","b","c","d","e"]) // 输出3,完全符合预期。

但这个方案有个问题:如果数组里有重复元素(比如arr1=["a","a"], arr2=["a","b"]),它会错误计算公共元素数,这时候我们需要统计元素的出现频率。

第二步:处理重复元素(用reduce统计频率)

reduce是用来累积数组元素生成单一结果的神器,最适合做频率统计。先写一个用reduce生成频率表的函数:

// 生成元素频率映射表:{元素: 出现次数}
function getFrequencyMap(arr) {
  return arr.reduce((frequencyMap, currentItem) => {
    // 如果当前元素已在映射表中,次数+1,否则设为1
    frequencyMap[currentItem] = (frequencyMap[currentItem] || 0) + 1;
    // 返回更新后的映射表,作为下一次循环的累积值
    return frequencyMap;
  }, {}); // 初始值是空对象,作为第一次循环的frequencyMap
}

这里给你拆解reduce的工作流程:

  • 第一个参数是回调函数,接收两个核心参数:frequencyMap(累积的结果,第一次是初始值{})和currentItem(当前遍历的数组元素)。
  • 每次循环更新映射表的计数,最后返回这个表,最终得到整个数组的频率统计。

有了频率表,我们就可以计算两个数组的真实公共元素总数(考虑重复次数):

function countDeletions(arr1, arr2) {
  const freq1 = getFrequencyMap(arr1);
  const freq2 = getFrequencyMap(arr2);
  
  let commonCount = 0;
  // 遍历其中一个频率表,取两个表中元素出现次数的最小值累加
  for (const key in freq1) {
    if (freq2[key]) {
      commonCount += Math.min(freq1[key], freq2[key]);
    }
  }
  
  return arr1.length + arr2.length - 2 * commonCount;
}

测试重复元素场景:countDeletions(["a","a"], ["a","b"]) // 输出2,正确(arr1删1个a,arr2删1个b,总删除2次)。

第三步:进一步优化(用一次reduce完成统计)

我们还可以省略第二个频率表,直接用reduce遍历第二个数组,同时消耗第一个频率表的计数,更高效:

function countDeletions(arr1, arr2) {
  // 先统计arr1的元素频率
  const freqMap = arr1.reduce((map, item) => {
    map[item] = (map[item] || 0) + 1;
    return map;
  }, {});
  
  // 遍历arr2,统计公共元素总数
  const commonCount = arr2.reduce((count, item) => {
    // 如果当前元素在arr1还有剩余次数,计数+1,同时减少频率表的次数
    if (freqMap[item] > 0) {
      count++;
      freqMap[item]--;
    }
    return count;
  }, 0); // 初始计数为0
  
  return arr1.length + arr2.length - 2 * commonCount;
}

这个版本只用了两次reduce,没有额外的循环,代码更简洁,效率也更高。

关于map的补充说明

你提到对map不熟悉,它的作用是把数组的每个元素转换成新元素,返回一个新数组,比如:

const arr = ["a", "b", "c"];
const upperArr = arr.map(item => item.toUpperCase()); // 输出["A", "B", "C"]

如果用map做频率统计,效率会很低(需要嵌套filter),所以这类统计场景reduce是更好的选择。

测试用例验证

  • 无公共元素:countDeletions(["x","y"], ["a","b"]) // 输出4
  • 完全相同数组:countDeletions(["a","b","c"], ["a","b","c"]) // 输出0
  • 多重复元素:countDeletions(["a","a","b"], ["a","b","b"]) // 输出2(最终可以是["a","b"],删1个a和1个b)

内容的提问来源于stack exchange,提问作者Martin Muldoon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:07:55