小编典典

存储数字流中最大的5000个数字

algorithm

鉴于以下问题:

“存储数字流中最大的5000个数字”

想到的解决方案是一个二叉搜索树,该树维​​护树中节点数的计数,并在计数达到5000时引用最小节点。当计数达到5000时,可以将要添加的每个新数字进行比较:树上最小的项目。如果更大,则可以添加新的数字,然后删除最小的数字,并计算出新的最小数字(这很简单,因为已经具有先前的最小数字)。

我对此解决方案的关注是,二叉树自然会偏斜(因为我只在一侧删除)。

有没有一种方法可以解决这个问题,而又不会造成严重歪斜的树?

万一有人想要它,到目前为止,我为我的解决方案提供了伪代码:

process(number)
{
  if (count == 5000 && number > smallest.Value)
  {
    addNode( root, number)
    smallest = deleteNodeAndGetNewSmallest ( root, smallest)
  }
}

deleteNodeAndGetNewSmallest( lastSmallest)
{
  if ( lastSmallest has parent)
  {
    if ( lastSmallest has right child)
    {
      smallest = getMin(lastSmallest.right)
      lastSmallest.parent.right = lastSmallest.right
    }
    else
    {
      smallest = lastSmallest.parent
    }
  }
  else 
  {
    smallest = getMin(lastSmallest.right)
    root = lastSmallest.right
  }
  count--
  return smallest
}

getMin( node)
{
  if (node has left)
    return getMin(node.left)
  else
    return node
}

add(number)
{
  //standard implementation of add for BST
  count++
}

阅读 236

收藏
2020-07-28

共1个答案

小编典典

最简单的解决方案是维持最大大小为5000
的最小

  • 每次有新数字到达时-检查堆是否小于5000(如果是)-添加它。
  • 如果不是,请检查最小值是否小于新元素,如果是,则将其弹出并插入新元素。
  • 完成后,您将拥有一个包含5000个最大元素的堆。

此解决方案很O(nlogk)复杂,其中n是元素数,并且k是您需要的元素数(在您的情况下为5000)。

也可以O(n)使用选择算法来完成-
存储所有元素,然后找到第5001个最大元素,并返回所有大于该元素的元素。但是,这很难实现,并且对于合理的大小输入-
可能不会更好。另外,如果流包含重复项,则需要更多处理。

2020-07-28