【问题标题】:Finding the second lowest frequent element from an array of integers?从整数数组中找到频率第二低的元素?
【发布时间】:2020-11-02 20:35:38
【问题描述】:

我正在寻找解决我遇到的 JavaScript 编码挑战,问题如下:

编写一个接受整数数组并返回该数组元素的函数。

该函数应确定每个元素的频率(该元素在数组中出现的次数),并尽可能返回频率第二低的元素。否则它应该返回频率最低的整数。

如果满足要求的元素不止一个,则应返回第二小的元素(根据值)。

示例输出:

secondLowest( [4, 3, 1, 1, 2] ) === 1

secondLowest( [4, 3, 1, 1, 2, 2] ) === 2

secondLowest( [4, 3, 1, 2] ) === 2

这是我到目前为止所得到的,尽管在此之后不知道如何最好地回答它:


    function mode(array) {
  if (array.length == 0) return null;
  let modeMap = {};
  let maxEl = array[0],
    maxCount = 1;
  for (let i = 0; i < array.length; i++) {
    var el = array[i];
    if (modeMap[el] == null) modeMap[el] = 1;
    else modeMap[el]++;
    if (modeMap[el] > maxCount) {
      maxEl = el;
      maxCount = modeMap[el];
    }
  }
  return maxEl;
}


【问题讨论】:

  • 挑战 ...请添加你的。
  • 第一个例子应该返回 2,而不是一个,对吧?
  • 第一个示例应该返回 2,或者第二个示例应该返回 1...
  • @MHebes 它返回 1,因为它说“尽可能应该返回频率第二低的元素”,因为 1 在那种情况下出现两次,其余出现一次(它的措辞不是很好,所以道歉)
  • @WillBuck 谢谢Will,感谢您的提醒,下次注意! :)

标签: javascript arrays frequency


【解决方案1】:

我决定给出一个通用的、参数化的函数,其中没有数字是硬编码的。

您的示例涉及两个硬编码值:

  • 应选择次低频率
  • 在平局的情况下,应选择次小

下面的代码是这样工作的:

  • 获取每个输入值的频率
  • 将所有具有相同频率的值组合在一起。
  • 按频率对这些分组对进行排序,然后选择第 n 个最低的(在您的情况下为 n=2
  • 如果第 n 个最低频率有多个对,请按 对这些对进行排序,然后选择第 m 个最低的对(在您的情况下为 m=2
  • 返回最后一对的值

我这里提到的mn参数在代码中分别称为freqIndvalInd。请注意,为了选择第二低的频率,freqInd 应该是 1,而不是 2(因为 0 会选择最低的频率,因此 1 会选择第二低的频率)。

let lowestFreqVal = (freqInd, valInd, values) => {
  
  // Calculate frequencies in a map
  let f = new Map();
  for (let v of values) f.set(v, (f.get(v) || 0) + 1);
  
  // Group together all val/freq pairs with the same frequency
  let ff = new Map();
  for (let [ val, freq ] of f) ff.set(freq, (ff.get(freq) || []).concat([ val ]));
  
  // Sort these groups by frequency
  let byFreq = [ ...ff ].sort(([ freq1 ], [ freq2 ]) => freq1 - freq2);  
  
  // Here are all the items of the `freqInd`-th lowest frequency, sorted by value
  // Note that `[1]` returns an array of integers at the frequency, whereas `[0]` would return the frequency itself
  let lowestItems = byFreq[ Math.min(byFreq.length - 1, freqInd) ][1]
    .sort((v1, v2) => v1 - v2);
  
  // Return the `valInd`-th lowest value
  return lowestItems[ Math.min(lowestItems.length - 1, valInd) ];
  
};

console.log('Some random examples:');
for (let i = 0; i < 10; i++) {
  // An array of random length, full of random integers
  let arr = [ ...new Array(3 + Math.floor(Math.random() * 5)) ]
    .map(v => Math.floor(Math.random() * 4));
  
  // Show the result of `lowestFreqVal` on this random Array
  console.log(`lowestFreqVal(1, 1, ${JSON.stringify(arr)}) = ${lowestFreqVal(1, 1, arr)}`);
}

这不是最佳解决方案,因为它使用sort。众所周知,在列表中找到某个第 n 个最大值的问题可以实现比sort 更好的运行时间(当n 是一个小值时,运行时间明显更好——我们可以直观地看到这一点,因为如果@ 987654336@,一次通过 (O(n)) 就可以了。

【讨论】:

  • 谢谢!非常有帮助,我仍然觉得代码很难理解,但会继续阅读,而且解释很深入。真的很感激!
  • 再次感谢您!非常感谢
猜你喜欢
  • 2021-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-08
  • 2020-04-12
  • 1970-01-01
相关资源
最近更新 更多