寻找离群数

时间:2019-02-06 03:09:21

标签: javascript arrays

我正在尝试解决CodeWars.com上的编码难题,我希望能在正确的方向上有所作为。假定以下函数采用一串数字(例如"2 4 7 8 10""1 2 2"等),并输出其偶数(偶数或奇数)不同的数字位置。 CodeWars.com的链接位于:https://www.codewars.com/kata/iq-test/train/javascript

在最后一个数字是不同数字("100 100 1""5 3 2")的测试中,我的功能似乎失败。有什么想法为什么我的功能会以这种方式执行?我一直在查看它,但看不到为什么会这样做:

function iqTest(numbers){
  let numArr = numbers.split(' ');
  let obj = {};
  obj.evenCount = 0;
  obj.oddCount = 0;
  console.log(numArr);

  for (let i = 0; i < numArr.length; i++) {
    if (numArr[i] % 2 === 0) {
      obj.evenCount += 1;
      obj.even = i + 1;
    } else {
      obj.oddCount += 1;
      obj.odd = i + 1;
    }
  }

  if (obj.even < obj.odd) {
    return (obj.even);
  } else {
    return (obj.odd);
  }
}

console.log(iqTest('5 3 2'));

3 个答案:

答案 0 :(得分:3)

您需要在函数末尾检查eventCountoddCount,而不是像这样检查oddevent属性:

if (obj.evenCount < obj.oddCount) {

之前,您正在检查哪个索引较高(即排名),但实际上您想检查哪个计数/频率较高。

请参见下面的工作示例:

function iqTest(numbers) {
  let numArr = numbers.split(' ');
  let obj = {};
  obj.evenCount = 0;
  obj.oddCount = 0;
  console.log(numArr);

  for (let i = 0; i < numArr.length; i++) {
    if (numArr[i] % 2 === 0) {
      obj.evenCount += 1;
      obj.even = i + 1;
    } else {
      obj.oddCount += 1;
      obj.odd = i + 1;
    }
    
    if(obj.oddCount > 0 && obj.evenCount > 0 && obj.oddCount !== obj.evenCount) { // early termination condition
      break; // break out of the loop is the difference between odd and even already exists
    }
  }

  if (obj.evenCount < obj.oddCount) { // change to check the counts
    return (obj.even);
  } else {
    return (obj.odd);
  }
}

console.log(iqTest("2 4 7 8 10")); // 3 (item: 7)
console.log(iqTest("1 2 2")); // 1 (item: 1)
console.log(iqTest("100 100 1")); // 3 (item: 1)
console.log(iqTest("5 3 2")); // 3 (item: 2)

答案 1 :(得分:2)

如前所述,代码中的问题是,您试图确定哪个占多数(奇数或偶数),但是您可以通过比较最后出现的位置({{1 }}和obj.odd),而不是出现次数obj.evenobj.evenCount)。

只需将其更改为此:obj.oddCount


也就是说,您的函数将始终遍历整个数组,但是您可以通过查看前三个数字来确定离群值是偶数还是奇数。出现较少,偶数或奇数的是异常值。

考虑到这一点,我们可以通过将其分为两个步骤来提高效率:

  1. 使用前三个数字来确定异常值是if (obj.evenCount < obj.oddCount) { ... }还是odd

  2. 找到异常值的第一个出现时退出,而不是搜索整个数组。

even

这里是一个稍微冗长的版本,用于将步骤分解为有意义的变量名:

function iqTest(stringOfNumbers) {
    let arr = stringOfNumbers.split(' ');
    let desiredRemainder = arr
      .slice(0,3)
      .reduce((evenCount, item) => item % 2 === 0 ? evenCount+1 : evenCount, 0) 
        > 1
          ? 1
          : 0;
    return arr.findIndex(i => i % 2 === desiredRemainder) + 1;
}
    
console.log(iqTest("3 4 7 9"));
console.log(iqTest("1 1 1 100"));
console.log(iqTest("5 2 3"));

  1. 我使用Array.reduce()来确定我们的赔率还是偶数。

  2. 如果离群值是奇数,我们正在寻找第一个项function iqTest(stringOfNumbers) { let arr = stringOfNumbers.split(' '); let firstThree = arr.slice(0,3); let evenCount = firstThree.reduce((evenCount, item) => item % 2 === 0 ? evenCount+1 : evenCount, 0); let desiredRemainder = evenCount > 1 ? 1 : 0; let indexOfOutlier = arr.findIndex(i => i % 2 === desiredRemainder); return indexOfOutlier+1; } console.log(iqTest("3 4 7 9")); console.log(iqTest("1 1 1 100")); console.log(iqTest("5 2 3"));(奇数)。

    如果离群数是偶数,我们正在寻找第一个项item % 2 === 1(偶数)。

  3. 然后我将该逻辑放在Array.findIndex()中,它将返回给定测试为item % 2 === 0的第一项的位置(并且我将true添加到其中复制代码)。

答案 2 :(得分:1)

根据数据的这种情况:

  

找出给定数字中的哪个不同于其他。鲍勃发现,一个数字通常与均匀度

中的其他数字不同

我将提供一种使用内置数组方法的替代方法,有关标准方法,请参考 Nick Parsons 答案:

function iqTest(numbers)
{
    return 1 + numbers.split(" ").findIndex(
        (x, idx, arr) => arr.filter(y => y % 2 === x % 2).length === 1
    );
}

console.log(iqTest("2 4 7 8 10")); // 3 (item: 7)
console.log(iqTest("1 2 2")); // 1 (item: 1)
console.log(iqTest("100 100 1")); // 3 (item: 1)
console.log(iqTest("5 3 2")); // 3 (item: 2)