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

在复杂度为O(n)的Javascript对象中查找3个最大值的键?,javascript,algorithm,sorting,big-o,javascript-objects,Javascript,Algorithm,Sorting,Big O,Javascript Objects,假设您有一个对象,例如: let objToCheck = { a: 2, b: 5, c: 9, d: 33 }; 如何按升序返回三个最大值的键,在本例中是:['c','h','d'],以线性时间为单位?显然,您需要循环整个对象一次,以比较所有值,但我很难想出一个不涉及嵌套循环的解决方案,我认为它是O(n²)。到目前为止,我的解决方案是这样的: function findBig3 (obj){ const res = []; const largest = Obje

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

let objToCheck = {
  a: 2, 
  b: 5,
  c: 9,
  d: 33
};
如何按升序返回三个最大值的键,在本例中是:
['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;
}

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

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

让objToCheck={
答:2,,
b:5,
c:9,
d:33,
e:4,
f:8,
g:3,
h:10
};
函数findBig3(obj){
return Object.keys(obj).sort((a,b)=>{return obj[b]-obj[a]}).slice(0,3);
}

log(findBig3(objToCheck))
如果您只是将
Object.values
更改为
Object.keys
并使用该键从原始对象中进行选择,则可以避免最后一个循环

让objToCheck={
答:2,,
b:5,
c:9,
d:33,
e:4,
f:8,
g:3,
h:10
};
函数findBig3(obj){
return Object.keys(obj).sort((a,b)=>{return obj[b]-obj[a]}).slice(0,3);
}
log(findBig3(objToCheck))此算法在O(n)中运行

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

注:

  • 这假设对象查找为O(1)。这最终取决于它在解释器中的实现方式,但它通常低于O(logn)
  • 这些条件当然可以优化。我将留给读者作为练习
  • 通常我们应该检查键是否属于对象实例,但这里我将假设输入对象不是从
    object.prototype
    继承的
  • 该算法在O(n)中运行

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

    注:

  • 这假设对象查找为O(1)。这最终取决于它在解释器中的实现方式,但它通常低于O(logn)
  • 这些条件当然可以优化。我将留给读者作为练习
  • 通常我们应该检查键是否属于对象实例,但这里我将假设输入对象不是从
    object.prototype
    继承的

  • 您可以在一个数组中不断推送3个对象并对数组进行排序,假设所需的元素数k充分小于n,这可以平均提供线性效率

    让objToCheck={
    答:2,,
    b:5,
    c:9,
    d:33,
    e:4,
    f:8,
    g:3,
    h:10
    };
    函数findBig3(obj){
    var res=[-1,-1,-1];
    用于(输入obj){
    res[3]=obj[key];
    res.sort(函数(a,b){返回b-a});
    }
    res.pop();
    返回res;
    }
    
    log(findBig3(objToCheck))您可以在一个数组中不断推送3个对象并对数组进行排序,假设您需要的元素数k足够小于n,这可以平均提供线性效率

    让objToCheck={
    答:2,,
    b:5,
    c:9,
    d:33,
    e:4,
    f:8,
    g:3,
    h:10
    };
    函数findBig3(obj){
    var res=[-1,-1,-1];
    用于(输入obj){
    res[3]=obj[key];
    res.sort(函数(a,b){返回b-a});
    }
    res.pop();
    返回res;
    }
    
    log(findBig3(objToCheck))
    .sort
    不是O(n)。
    .sort
    不是O(n)。这与这完全没有区别。这与我们也可以创建一个包含4个元素的数组,并始终将最新的元素放在末尾,以避免调用
    .push
    .pop
    @Derek朕會功夫 是的,那会更好,谢谢你的建议,代码更新。我们还可以创建一个包含4个元素的数组,并始终将最新的元素放在末尾,以避免调用
    .push
    .pop
    @Derek朕會功夫 是的,那会更好,谢谢你的建议,代码更新。
    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];
    }