Big O表示法用于`.forEach`和`.find`。

huangapple go评论50阅读模式
英文:

Big O notation for .forEach with .find

问题

这段代码的时间复杂度是O(N),而不是O(N^3)。尽管它包含了一个.forEach循环以及两个.find()操作,但这些操作在这种情况下不会导致O(N^3)的复杂度。.forEach循环遍历_data.validatorInfo.result.validators数组,其中N是数组的长度。内部的.find()操作是在不同的数组上执行的,但它们是线性操作,因此它们的复杂度仍然是O(N)。因此,整体的时间复杂度是O(N)。

英文:

What is the big O notation for the following code?

    _data.validatorInfo.result.validators.forEach((_validator) => {
        let del = {
            delegation: _data.delegations.result.delegation_responses.find(
                res => res.delegation.validator_address === _validator.operator_address
            ),
            validator: _validator,
            rewards: _data.totalRewards.result.rewards.find(
                re => re.validator_address === _validator.operator_address
            )
        }
        result.delegations.push(del);
    })

Since it has a .forEach and two .find() operations nested, can I assume it is O(N^3)?

答案1

得分: 2

你遍历所有的validators(V),对于每一个,遍历delegation_responses(P)和rewards(W),直到找到特定的元素,这平均意味着要遍历数组的一半。

这将给你V * (P + W)/2。大O符号忽略常数因子(将它们设为1),因此得到O(V * (P + W))。此时,可以进行以下讨论:

  • 如果P和W与V相比非常小(数量级上),您可以认为它们行为类似于常数,并且只稍微扩展了主要因素V,从而获得有效线性复杂度O(N),其中N是验证者的数量。

  • 如果V非常小(再次是数量级上)与P和/或W相比,您将获得O(N)O(N + M),其中N和M是响应/奖励的数量,再次认为V行为类似于一个常数。

  • 如果它们都差不多大(或者你不能对它们的大小做出假设),你将得到O(N * 2N),也就是O(N²)

英文:

You go through all validators (V), for each of them going through delegation_responses (P) and rewards (W) until a certain element is found, which on average means to go through half of the array .

This would give you V * (P + W)/2. Big O ignores constants factors (sets them to 1), so that gives you O(V * (P + W)). And at that point, you can start arguing:

  • If P and W are very small compared to V (like orders of magnitude), you would argue that they behave like constants and only slightly scale the driving factor V, and you deal with effectively linear complexity O(N), where N is the number of validators.

  • If V is very small (again, orders of magnitude) compared to P and/or W, you would get O(N) or O(N + M), where N and M are number of responses/rewards, again arguing that V behaves like a constant.

  • If they are all about the same size (or you cannot make assumptions about their size), you get O(N * 2N), which is O(N²).

答案2

得分: 2

你的复杂度是

O(N*(M+Q)),其中

  • N 是 _data.validatorInfo.result.validators.length
  • M 是 _data.delegations.result.delegation_responses.length
  • Q 是 _data.totalRewards.result.rewards.length

可以假设这个复杂度

  • 如果 N ~ M+Q,则为二次复杂度
  • 如果 N >> M + Q,则为线性复杂度
英文:

Your complexity is

O(N*(M+Q)), where

  • N is _data.validatorInfo.result.validators.length
  • M is _data.delegations.result.delegation_responses.length and
  • Q is _data.totalRewards.result.rewards.length

You can assume that this

  • is quadric if N ~ M+Q
  • linear if N >> M + Q

答案3

得分: 1

不直接回答你的问题,我想指出性能可以很容易地改进。一种常见的方法是使用哈希表(ObjectMap)来查找你要查找的项目。

const delegations = new Map();
_data.delegations.result.delegation_responses.forEach((res) => {
  delegations.set(res.delegation.validator_address, res);
});

const rewards = new Map();
_data.totalRewards.result.rewards.forEach((re) => {
  rewards.set(re.validator_address, re);
});

_data.validatorInfo.result.validators.forEach((_validator) => {
  result.delegations.push({
    delegation: delegations.get(_validator.operator_address),
    validator: _validator,
    rewards: rewards.get(_validator.operator_address),
  });
});

使用与Radu Diță的回答相同的字母。

  • N为_data.validatorInfo.result.validators.length
  • M为_data.delegations.result.delegation_responses.length
  • Q为_data.totalRewards.result.rewards.length

这个改进版本将导致复杂度为O(N+M+Q)


如果你的情况允许,你可能可以使用以下方式:

result.delegations = _data.validatorInfo.result.validators.map(...);
英文:

Rather than answering your question directly, I want to point out that performance can be improved very easily. A common way to do this would be to use a hash table (Object or Map) to find the items you're looking for.

const delegations = new Map();
_data.delegations.result.delegation_responses.forEach((res) => {
  delegations.set(res.delegation.validator_address, res);
});

const rewards = new Map();
_data.totalRewards.result.rewards.forEach((re) => {
  rewards.set(re.validator_address, re);
});

_data.validatorInfo.result.validators.forEach((_validator) => {
  result.delegations.push({
    delegation: delegations.get(_validator.operator_address),
    validator: _validator,
    rewards: rewards.get(_validator.operator_address),
  });
});

Using the same letters as the answer of Radu Diță

> - N is _data.validatorInfo.result.validators.length
> - M is _data.delegations.result.delegation_responses.length and
> - Q is _data.totalRewards.result.rewards.length

This improved version would result in complexity O(N+M+Q).


You might be able to use

result.delegations = _data.validatorInfo.result.validators.map(...);

if your scenario allows for it.

huangapple
  • 本文由 发表于 2023年3月31日 17:24:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/75896816.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定