线段树的查询代码
public E query(int queryL,int queryR){
if(queryL<0||queryL>=data.length||queryR<0||queryR>=data.length||queryL>queryR)
throw new IllegalArgumentException("index illegal");
return query(0,0,data.length-1,queryL,queryR);
}
//从线段树的treeIndex 索引开始在区间data[l:r]查找queryL,queryR 的值
private E query(int treeIndex,int l,int r,int queryL,int queryR){
if(l==queryL && r==queryR){
return tree[treeIndex];
}
int mid=l+(r-l)/2;
if(queryL>=l && queryR<=mid)
return query(leftChild(treeIndex),l,mid,queryL,queryR);
else if(queryL>=mid+1&&queryR<=r)
return query(rightChild(treeIndex),mid,r,queryL,queryR);
return merger.merge(query(leftChild(treeIndex),l,mid,queryL,mid),query(rightChild(treeIndex),mid,r,mid,queryR));
}
测试
public class Main {
public static void main(String[] args) {
Integer[] nums={-2,0,3,-5,2,-1};
//匿名类
Merger<Integer> merger=new Merger<Integer>() {
@Override
public Integer merge(Integer a, Integer b) {
return a+b;
}
};
SegmentTree<Integer>segTree=new SegmentTree<>(nums,merger);
SegmentTree<Integer>segTree2=new SegmentTree<>(nums,(a,b)->a+b);//lambda 表达式
System.out.println(segTree.toString());
System.out.println(segTree.query(0,2));
System.out.println(segTree.query(0,5));
}
}
求解
303. 区域和检索 - 数组不可变
public class NumArray2 {
private SegmentTree<Integer>segmentTree;
public NumArray2(int []nums){
if(nums.length>0){
Integer[]data=new Integer[nums.length];
for (int i=0;i<nums.length;i++)
data[i]=nums[i];
segmentTree=new SegmentTree<> (data,(a,b)->a+b);
}
}
public int sumRange(int i,int j){
return segmentTree.query(i,j);
}
}
完整版
public class NumArray {
private interface Merger<E> {
E merge(E a,E b);
}
private class SegmentTree<E> {
private E[] tree;
private E[] data;
private Merger<E>merger;
public SegmentTree(E[] arr,Merger<E> merger){
this.merger=merger;
data=(E[])new Object[arr.length];
for(int i=0;i<arr.length;i++){
data[i]=arr[i];
}
//用数组表示树类型结构
tree=(E[])new Object[4*arr.length];
buildSegmentTree(0,0,data.length-1);//线段树的根结点索引为0
}
//递归构建索引为树结点treeindex 对应data区间[l,r]的信息
public void buildSegmentTree(int treeindex,int l,int r){
if(l==r){
tree[treeindex]=data[l];
return;
}
int treeleftchildindex=leftChild(treeindex);
int treerightchildindex=rightChild(treeindex);
int mid=l+(r-l)/2;
buildSegmentTree(treeleftchildindex,l,mid);
buildSegmentTree(treerightchildindex,mid+1,r);
// tree[treeindex]=+
tree[treeindex]=merger.merge(tree[treeleftchildindex],tree[treerightchildindex]);
}
public int getSize(){
return data.length;
}
public E get(int index){
if(index<0||index>=data.length)
throw new IllegalArgumentException("index is illeagal");
return data[index];
}
public int leftChild(int index){
return 2*index +1;
}
public int rightChild(int index){
return 2* index +2;
}
public E query(int queryL,int queryR){
if(queryL<0||queryL>=data.length||queryR<0||queryR>=data.length||queryL>queryR)
throw new IllegalArgumentException("index illegal");
return query(0,0,data.length-1,queryL,queryR);
}
//从线段树的treeIndex 索引开始在区间data[l:r]查找queryL,queryR 的值
private E query(int treeIndex,int l,int r,int queryL,int queryR){
if(l==queryL && r==queryR){
return tree[treeIndex];
}
int mid=l+(r-l)/2;
if( queryR<=mid)
return query(leftChild(treeIndex),l,mid,queryL,queryR);
else if(queryL>=mid+1)
return query(rightChild(treeIndex),mid+1,r,queryL,queryR);
return merger.merge(query(leftChild(treeIndex),l,mid,queryL,mid),query(rightChild(treeIndex),mid+1,r,mid+1,queryR));
}
@Override
public String toString(){
StringBuilder res=new StringBuilder();
res.append('[');
for(int i=0;i<tree.length;i++){
if(tree[i]!=null) res.append(tree[i]);
else res.append("null");
if(i!=tree.length-1) res.append(" ");
}
res.append(']');
return res.toString();
}
}
private SegmentTree<Integer>segmentTree;
public NumArray(int []nums){
if(nums.length>0){
Integer[]data=new Integer[nums.length];
for (int i=0;i<nums.length;i++)
data[i]=nums[i];
segmentTree=new SegmentTree<> (data,(a,b)->a+b);
}
}
public int sumRange(int i,int j){
if(segmentTree==null)
throw new IllegalArgumentException("nums is null");
return segmentTree.query(i,j);
}
}
/**
* Your NumArray object will be instantiated and called as such:
* NumArray obj = new NumArray(nums);
* int param_1 = obj.sumRange(i,j);
*/