区间最值和区间求和问题
力扣相关题目:
平衡二叉树,数组中的元素都存储在叶子结点中,如图是一个求区间最大值的线段树。
已知数组arr[11,5,3,7,8,2] ,树的高度与数组的长度关系为:

为了方便我们用代码实现线段树,将创建的数为满二叉树,如下图举例

T[] data存储传入的原数组
T[] treeData存储构建的平衡二叉树
Merge
merge 融合器,表示线段树中节点值的计算方式
Merge接口:
- public interface Merge
{ - T merge(T v1,T v2);
- }
线段树:
- import java.util.Arrays;
-
- public class SegmentTree
{ -
- //原数组
- private T[] data;
- //构建的平衡二叉树的数组
- private T[] treeData;
-
- private Merge
merge; -
- public SegmentTree(T[] arr,Merge
merge) { - // 入参判断
- if (arr==null||arr.length==0){
- return;
- }
- this.merge = merge;
-
- //将数组赋值到我们的原数组中
- this.data = Arrays.copyOf(arr,arr.length);
-
- //计算树的高度
- int h = (int)Math.ceil(Math.log10(arr.length)/Math.log10(2)+1);
- //平衡二叉树节点个数
- int length = (int)Math.pow(2,h)-1;
- //初始化树
- this.treeData = (T[]) new Object[length];
- // 构建平衡二叉树
- this.buildingSegmentTree(0,arr.length-1,0);
- }
-
- /**
- * 构建平衡二叉树
- * @param left 原数组的左边索引
- * @param right 原数组的右边索引
- * @param index 构建树的索引
- */
- private void buildingSegmentTree(int left,int right,int index){
- // 递归终止条件
- if (left==right){
- this.treeData[index] = this.data[left];
- return;
- }
- // 递归操作
- int mid = left+(right-left)/2;
- buildingSegmentTree(left,mid,2*index+1);
- buildingSegmentTree(mid+1,right,2*index+2);
- //计算当前节点的值
- this.treeData[index] = this.merge.merge(this.treeData[2*index+1],this.treeData[2*index+2]);
- }
-
-
-
- //查询
- public T query(int from,int to){
- if (from<0||to>this.data.length||to
- return null;
- }
- return query(0,this.data.length-1,0,from,to);
- }
- /**
- *
- * @param left 原数组的左位置
- * @param right 原数组的右位置
- * @param index 平衡二叉树的中对应节点的索引
- * @param from 所求索引的开始位置
- * @param to 所求索引的结束位置
- * @return
- */
- private T query(int left,int right,int index,int from,int to){
- //找到区间
- if (left==from&&right==to){
- return this.treeData[index];
- }
- int mid = left + (right-left)/2;
- if (to<=mid){//去左找
- return query(left,mid,index*2+1,from,to);
- }else if (from>mid){//去右找
- return query(mid+1,right,index*2+2,from,to);
- }else {//两遍都有
- T leftVal = query(left,mid,index*2+1,from,mid);
- T rightVal = query(mid+1,right,index*2+2,mid+1,to);
- return this.merge.merge(leftVal,rightVal);
- }
- }
-
- public static void main(String[] args) {
- Integer[] arr = {1,3,5,7,9,11};
- SegmentTree
tree = new SegmentTree(arr,(v1,v2)->v1>v2?v1:v2); - int res = tree.query(2,4);
- System.out.println(res);
- }
- }
测试:
- public static void main(String[] args) {
- Integer[] arr = {11,5,3,6,7,8,2};
- SegmentTree
tree = new SegmentTree(arr,(v1,v2)->v1>v2?v1:v2); - int res = tree.query(2,4);
- System.out.println(res);//7
- }