【问题标题】:Is it possible to build a Fenwick tree in O(n)?是否可以在 O(n) 中构建 Fenwick 树?
【发布时间】:2015-06-26 08:32:02
【问题描述】:

Fenwick tree 是一种允许两种操作的数据结构(您可以通过更多操作来扩充它):

  • 点更新update(index, value)
  • 前缀和query(index)

这两个操作都在O(log(n)) 中,其中n 是数组的大小。我对如何执行这两种操作及其背后的逻辑没有任何问题。


我的问题是如何从数组中初始化 Fenwick 树。显然我可以在O(nlog(n)) 中实现这一点,通过调用nupdate(i, arr[i]),但是有没有办法在O(n) 中初始化它。


如果维基百科告诉你可以在nlog(n) 中初始化,我为什么要问这个?因为这篇文章太简陋了,所以我不确定它是否是可以达到的最佳复杂性。还与简单的堆创建相似,这是通过逐个填充堆来完成的,可以在O(nlog(n)) 中实现,而O(n) 中的智能堆初始化让我希望可以在 Fenwick 树中完成类似的事情。

【问题讨论】:

  • @DavidEisenstat 没有重复,因为检查了O(n*log(n)) 的算法,这里要求并提供了一个O(n) 算法。虽然很好找。
  • @Vesper 这是一个 O(n log n) 时间的算法,更仔细地分析为 O(n)。
  • 关于@DavidEisenstat 链接到的问题的更新表明,所讨论的算法毕竟不是天真的算法(从经验上看似乎是 Omega(n log n)),而是一个实际上与我的非常相似——唯一的区别是它“拉”值而不是“推”它们。

标签: algorithm fenwick-tree


【解决方案1】:

[编辑:我把事情“颠倒了”——现在修好了!]

是的。以递增的索引顺序遍历 n 个数组项,始终将总和 only 添加到应该添加到的下一个最小索引,而不是添加到所有索引:

for i = 1 to n:
    j = i + (i & -i)     # Finds next higher index that this value should contribute to
    if j <= n:
        x[j] += x[i]

这是可行的,因为尽管每个值都对多个范围和有贡献,但在处理了该值贡献的最底部范围和之后(实际上不需要“处理”,因为总和已经存在),我们不再需要维护它的独立标识——它可以安全地与对剩余范围总和有贡献的所有其他值合并。

TTBOMK 这个算法是“新的”——但我并没有看得很辛苦;)

【讨论】:

  • 令人印象深刻!虽然这会破坏起始数组,但始终可以将其复制到其他地方并处理副本。
  • 非常有趣的方法!
  • 我也认为你忘记了 abt x[i]+=array_element[i];在 if 条件语句之前
  • @rushikeshchaskar:x[] 是起始数组——算法是就地的,即将这个数组修改为 Fenwick 树。
【解决方案2】:

这是 Java 实现:

public BIT(long[] nums) {
        bit = new long[nums.length + 1]; //one-indexed
        for (int i = 1; i <= nums.length; i++) {
            bit[i] += nums[i - 1]; //update node
            if (i + (i & -i) <= nums.length) {
                bit[i + (i & -i)] += bit[i]; //update parent
            }
        }
    }

与 j_random_hacker 的帖子相同的一般思想:我们更新当前节点和下一个更高的父节点,使用所有子节点将始终在其各自的父节点之前访问的属性

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-20
    • 2021-03-10
    • 2013-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-30
    相关资源
    最近更新 更多