leetcode307.Range Sum Query - Mutable
题目要求
1 | Given an integer array nums, find the sum of the elements between indices i and j (i ≤ j), inclusive. |
可以先参考数组不发生变动时的题目。
这里的难度在于数组可以在中间出现变动,那么面对大容量数组的时候如何选择一个合适的数据结构及很重要。
思路一:map缓存
最开始我们有两种直观的想法,一种是在插入时同时更新后面所有的和,这意味着O(n)的插入复杂度和O(1)的读取复杂度。我决定选择第二种方式,也就是采用类似日志的形式记录下每一次的变更。这样当我们读取的时候,再遍历日志,将相关的变更结果添加到当前的数值上。缺点是,变更很多以及数组很庞大时,效率依然很差。
这个方法超时了。
1 | private int[] sum; |
思路二:Segment Tree
我们将一个数组转化为一棵树,其中当前的数组被均匀的分割并且分别用左子数组和右子数组构建左子树和右子树。最后的叶节点为当前数组的值,非叶结点则记录了子数组的范围以及该子数组中所有元素的和。
举个例子说明一下:
假设当前的数组为[1,2,5],则构成的Segment Tree为:
1 | 8 |
这里先将[1,2,5]分割为[1,2]和[5]两个子数组,然后分别构造子树。最后的树如上所示。
1 | class SegmentTreeNode{ |
要想了解更多关于Segment Tree,请参考这篇文章。
思路三:Binary Indexed Tree
网上有非常多的关于二进制索引数树的教程。它是一个非常轻量级的数据结构,而且几乎就是为这种题目量身打造。可以先从这篇文章和这篇文章了解一下。
1 | class NumArray { |