在具有O(n)复杂度的Javascript对象中查找3个最大值的键?

时间:2017-08-17 23:09:13

标签: javascript algorithm sorting big-o javascript-objects

假设您有一个对象,例如:

let objToCheck = {
  a: 2, 
  b: 5,
  c: 9,
  d: 33,
  e: 4,
  f: 8,
  g: 3,
  h: 10
};

你将如何以升序返回三个最大值的键,在这种情况下,它将是:[ 'c', 'h', 'd' ],在线性时间内?显然你需要遍历整个对象一次来比较所有的值,但是我遇到了一个麻烦的解决方案,它不涉及嵌套循环,我认为是O(n²)。以下是我目前的解决方案:

function findBig3(obj){
  const res = [];
  const largest = Object.values(obj).sort((a,b) => {return b-a}).slice(0,3);

  for (let key in obj){
    largest.forEach( (val) => {
      if (obj[key] === val) res.push(key);
    });
  }
  return res;
}

我认为您需要声明三个变量,例如big1big2big3,并且在循环对象时执行某种类型的比较检查并根据需要重新分配,但我正在努力实施。

3 个答案:

答案 0 :(得分:2)

你可以继续推动数组中的3个对象并继续对数组进行排序,假设你需要的元素数量k足够小于n,这可以平均提供线性效率。

let objToCheck = {
  a: 2, 
  b: 5,
  c: 9,
  d: 33,
  e: 4,
  f: 8,
  g: 3,
  h: 10
};


function findBig3(obj){
  var res = [-1,-1,-1];

  for (let key in obj){
   res[3] = obj[key];
   res.sort(function(a,b){return b-a});
  }
  res.pop();
  return res;
}


console.log(findBig3(objToCheck));

答案 1 :(得分:1)

该算法在O(n)中运行。

function getThreeLargestKeys(obj){
    var k1, k2, k3;
    var v1, v2, v3;
    v1 = v2 = v3 = -Infinity;

    // O(1)
    var insertKey = function(key){
        var value = obj[key];  // note 1

        // note 2
        if(value >= v1){
            v3 = v2; v2 = v1; v1 = value;
            k3 = k2; k2 = k1; k1 = key;
        }else if(value >= v2){
            v3 = v2; v2 = value;
            k3 = k2; k2 = key;
        }else if(value >= v3){
            v3 = value;
            k3 = key;
        }
    };

    // O(n)
    for(var key in obj){
        // note 3
        insertKey(key);
    }

    return [k1, k2, k3];
}

https://jsfiddle.net/DerekL/pzatq729/

请不要将代码复制粘贴到作业中作为解决方案。一旦你完全理解它,就重写代码。

注意:

  1. 这假设对象查找是O(1)。这最终取决于它在解释器中的实现方式,但通常低于O(log n)。
  2. 这些条件肯定可以优化。我将把它作为读者的练习。
  3. 通常我们应检查密钥是否归对象实例所有,但在这里我假设输入对象不是从Object.prototype继承的。

答案 2 :(得分:0)

如果您只是将Object.values更改为Object.keys并使用该键从原始对象中进行选择,则可以避免上一次循环。

let objToCheck = {
  a: 2,
  b: 5,
  c: 9,
  d: 33,
  e: 4,
  f: 8,
  g: 3,
  h: 10
};

function findBig3(obj){
  return Object.keys(obj).sort((a,b) => {return obj[b]-obj[a]}).slice(0,3);
}

console.log(findBig3(objToCheck));