Data structures 用于存储数据和计算平均值的数据结构

Data structures 用于存储数据和计算平均值的数据结构,data-structures,average,Data Structures,Average,在这个问题中,我们感兴趣的是一种支持保持无限多个Y轴平行向量的数据结构 每个节点都包含位置(X轴值)和高度(Y轴值)。我们可以假设在同一位置没有两个向量 请提供有效的数据结构,以支持: init((x1,y1)(x2,y2)(x3,y3)…(xn,yn))< /代码> -DS将包含所有n个向量,而向量i i的位置是席向量,i是HIGHT。 我们还知道x1注意更新(x,y)< /> >在O(log n)中运行,如果你有这样的结构:如果你更新元素 x 到高度>代码> y>代码>,你必须考虑平均值

在这个问题中,我们感兴趣的是一种支持保持无限多个Y轴平行向量的数据结构

每个节点都包含位置(X轴值)和高度(Y轴值)。我们可以假设在同一位置没有两个向量

请提供有效的数据结构,以支持:

<代码> init((x1,y1)(x2,y2)(x3,y3)…(xn,yn))< /代码> -DS将包含所有n个向量,而向量i i的位置是席向量,i是HIGHT。 我们还知道
x1
(对y一无所知)-平均复杂度=O(n)

  • 插入(x,y)
    -添加位置为x、高度为y的向量复杂性=平均摊销的O(logn)

  • 更新(x,y)
    -将向量#x的高度更新为y.-复杂性=O(logn)最坏情况

  • average_about(x)
    -返回x-complexity=O(1)的logn邻居的平均高度


  • 空间复杂性:O(n)

    我不能提供一个完整的答案,但它可能是一个指向正确方向的提示

    基本理念

    • 假设您已经计算了
      n
      数字
      a_1,…,a_n
      的平均值,那么这个平均值是
      avg=(a_1+…+a_n)/n
      。如果我们现在用
      b
      替换
      a\u n
      ,我们可以如下重新计算新的平均值:
      avg'=(a\u 1+…+a\u(n-1)+b)/n
      ,或者-simpler-
      avg'=((avg*n)-a\u n+b)/n
      。这意味着,如果我们交换一个元素,我们可以通过简单、快速的操作使用原始平均值重新计算平均值,而不需要对参与平均值的所有元素进行重新迭代
    注意:我假设您希望每侧都有
    logn
    邻居,即我们总共有
    2个log(n)
    邻居。如果希望总共有
    log(n)
    邻居,您可以简单地调整它。此外,由于
    logn
    在大多数情况下都不是一个自然数,因此我假设您所说的是
    floor(logn)
    ,但为了简单起见,我只写
    logn

    我考虑的主要问题是,在O(1)中,你必须告诉元素
    x
    周围的平均值。因此,我想你必须以某种方式预先计算这个平均值并存储它。因此,我将在节点中存储以下内容:

    • x值
    • y值
    • 平均约
    <> >注意<代码>更新(x,y)< /> >在O(log n)中运行,如果你有这样的结构:如果你更新元素<代码> x <代码>到高度>代码> y>代码>,你必须考虑平均值受这个变化影响的2log(n)< /代码>邻居。您可以在O(1)中重新计算这些平均值:

    让我们假设,
    update(x,y)
    影响一个元素
    b
    ,其平均值也要更新。然后,您只需将
    average(b)
    乘以邻居的数量(
    2log(n)
    ,如上所述)。然后,我们减去元素
    x
    的旧
    y-value
    ,并添加
    x
    的新(更新的)
    y
    -值。然后,我们除以
    2 log(n)
    。这确保我们现在有元素
    b
    的更新平均值。这只涉及一些计算,因此可以在O(1)中完成。由于我们有
    2logn
    邻居,
    update
    O(2logn)=O(logn)
    中运行

    插入新元素
    e
    时,必须更新受此新元素
    e
    影响的所有元素的平均值。这基本上是在
    更新
    例程中完成的。但是,当
    logn
    (或者确切地说
    floor(logn)
    )更改其值时,您必须小心。如果
    floor(log n)
    保持不变(在大多数情况下会保持不变),则您可以执行
    update
    中描述的模拟操作,但是您必须“删除”一个元素的高度,并“添加”新添加元素的高度。在这些“良好”的情况下,运行时间再次严格限制为
    O(logn)

    现在,当
    floor(logn)
    正在更改(递增1)时,您必须对所有元素执行更新。也就是说,您必须对
    n
    元素执行O(1)操作,从而导致运行时间
    O(n)
    。然而,
    floor(logn)
    增加1的情况非常罕见(您需要将
    n
    的值加倍,以将
    floor(logn)
    增加1-假设我们讨论的是
    log
    以2为基数,这在计算机科学中并不少见)。我们用
    c*n
    或简单地
    cn
    来表示这个时间

    因此,让我们考虑一个插入序列:第一个插入需要更新:<代码> C* 1 ,第二个插入需要更新:<代码> 2 *c>代码>。下次发生昂贵的插入时,是第四次插入:

    4*c
    ,然后是第八次插入:
    8c
    ,第六次插入:
    16*c
    。两个昂贵插件之间的距离每次增加一倍:

    insert # 1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16  17  18 ..
    cost     1c 2c 1  4c 1  1  1  8c 1  1   1   1   1   1   1   16c 1   1  ..
    

    由于没有<代码>删除< /代码>,我们可以继续分析,没有任何“特殊情况”,只考虑插入序列。您可以看到,大多数插入成本为1,而很少有插入成本昂贵(1,2,4,8,16,32,…)。因此,如果我们总共有

    m
    插入,我们大概有
    log m
    昂贵的插入,以及大约
    m-log m
    便宜的插入。为简单起见,我们只假设
    m
    廉价插入

    然后,我们可以计算
    m
    插入的成本:

             log m
             ----
             \      i
    m*1 +    /     2   
             ----
              i=0
    
    m*1
    计算便宜的操作,计算昂贵操作的总和。可以看出,整个过程最多是
    4m
    (事实上,您甚至可以很容易地显示更好的估计,但对我们来说,这就足够了)

    因此,我们看到,
    m
    插入操作的总成本最多为
    4m
    。因此,单次插入操作的成本最高不超过