【问题标题】:Finding the integer that appears an odd number of times查找出现奇数次的整数
【发布时间】:2020-08-11 18:09:30
【问题描述】:

问题

给定一个整数数组,找出出现奇数次的那个。

总是只有一个整数出现奇数次。

我的尝试

function findOdd(A) {
  let newArr = A.sort();
  let altArr = [];
  let count = 0;
  let firstCharacter = newArr[0];

  for (let i = 0; i < newArr.length; i++) {
    if (newArr[i] == firstCharacter) {
      count++;

    } else {
      let subArr = newArr.slice(newArr[0], count);
      console.log(subArr);
      altArr.push(subArr);
      count = 0;
      firstCharacter = newArr[i];
    }
  }
  for (let i = 0; i < altArr.length; i++) {
    if (altArr[i].length % 2 != 0) {
      return altArr[i][0];
    }
  }
}


console.log(findOdd([20, 1, -1, 2, -2, 3, 3, 5, 5, 1, 2, 4, 20, 4, -1, -2, 5]))

问题

我使用控制台日志显示切片返回一个空数组,我认为这就是该算法被破坏的原因。但是为什么它返回一个空数组呢?还有我遗漏的其他错误吗?

【问题讨论】:

  • slice() 的第一个参数是数组索引。为什么要使用数组元素作为参数?
  • 我不明白为什么,从逻辑上讲,你需要切片。从逻辑上讲,您似乎只是从 0 循环到 n - 1,抓取元素,并计算它出现的次数。第一个奇怪的你会退回它。对我来说,这并没有说明我需要对数组进行切片。
  • 我正在切片,以便我可以取出所有相同的并将它们分组以便于计数。

标签: javascript algorithm


【解决方案1】:

您使这个问题比实际情况复杂得多。一个简单的实现会简单地使用一个对象来存储每个元素的频率,然后在最后迭代它以找到出现奇数次的元素。

function findOdd(arr) {
    const freq = {};
    for(const num of arr){
        freq[num] = (freq[num] || 0) + 1;
    }
    return +Object.keys(freq).find(num => freq[num] % 2 == 1);
}

更有效的实现可以利用按位 XOR (^) 的属性,即 a ^ a == 0a ^ 0 == a 以及该操作是可交换和关联的,从而导致应用 XOR 的解决方案数组中的每个元素来获取答案。

function findOdd(arr) {
    return arr.reduce((a,c)=>a ^ c, 0);
}

【讨论】:

  • 这应该是公认的答案。 XOR 非常节省时间和空间。
【解决方案2】:

newArr.slice(newArr[0], count); slice 需要 2 个参数,它们需要是索引,而不是实际值。所以上面的代码肯定是不正确的。 我认为您可以使用字典来简化此算法。这是我的方法。

function findOdd(A) {
    const appearances = {};
    A.forEach(val => {
        appearances[val] = (appearances[val] || 0) + 1;
    });
    const oddNumbers = Object.keys(appearances).filter(key => appearances[key] % 2 != 0);
    return oddNumbers.length > 0 ? oddNumbers[0] : NaN;
}

【讨论】:

    【解决方案3】:

    排序后,您可以进行一个循环并根据最后一个值检查该值(初始化时没有值)。

    function findOdd(array) {
        let count = 0;
        let last;
    
        array.sort();
    
        for (let i = 0; i < array.length; i++) {
            if (array[i] === last) {
                count++;
                continue;
            } 
            if (count % 2) return last;
            last = array[i];
            count = 1;
        }
        return last;
    }
    
    console.log(findOdd([20, 1, -1, 2, -2, 3, 3, 5, 5, 1, 2, 4, 20, 4, -1, -2, 5]))
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    【讨论】:

    • 继续做什么?
    • "continue statement 终止当前或标记循环的当前迭代中语句的执行,并在下一次迭代中继续执行循环。"
    • 您错过了基于 XORing 的解决方案。这是一个经典的技巧。
    • @YvesDaoust,是的,这个答案是重复的。但 op 要求提供给定的代码/方法。
    猜你喜欢
    • 2020-01-15
    • 2017-09-13
    • 2023-03-19
    • 1970-01-01
    • 2015-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多