LeetCode-307
线段树是一种非常灵活的数据结构,它可以用于解决多种范围查询问题,比如在对数时间内从数组中找到最小值、最大值、总和、最大公约数、最小公倍数等。
数组 A[0,1,…,n−1] 的线段树是一个二叉树,其中每个节点都包含数组的一个子范围 [i…j] 上的聚合信息(最小值、最大值、总和等),其左、右子节点分别包含范围 [i … (i+j)/2]和 [(i+j)/2 + 1, j]上的信息。
class NumArray {
public interface Merger<E> {
E merge(E a, E b);
}
public class SegmentTree<E> {
/*
使用一个数组表示区间.
首先,用户可能要获取区间内的某一个元素,或者获取区间的某一个属性,我们在线段树中创建数组,作为区间数组的的副本,用于给出区间数组的某些属性;
其次,我们想将data数组内的元素(arr数组传递进来的)组织成为一个线段树,那么还需要创建一个tree,大小为 4 * size
*/
private E[] data;
//tree结点虽然表示的是一个区间,但是它里面存储的实际上是区间内数据按一定方式计算得到的值。
private E[] tree;
private Merger<E> merger;
//初始化的时候传入一个区间数组
public SegmentTree(E[] arr , Merger<E> merger) {
this.merger = merger;
data = (E[])new Object[arr.length]; // 使用arr初始化data
for (int i = 0; i < arr.length ; i++) {
data[i] = arr[i];
}
tree = (E[])new Object[arr.length * 4];
//调用 buildSegmentTree() 方法,完成线段树数组tree每一个结点 data数组区间的确定!
buildSegmentTree(0 , 0 , data.length-1); //线段树从0位置开始赋予区间,此时区间为data最大区间:0-data.length-1
}
public int getSize() {
return data.length;
}
public E get(int index) {
if(index < 0 || index >= data.length)
throw new IllegalArgumentException("Index is illegal.");
return data[index];
}
// 返回满二叉树的数组表示中,一个索引所表示的元素的左孩子节点的索引
private int<