描述:
对于一个数组,我们可以对其建立一棵 线段树
, 每个结点存储一个额外的值 count
来代表这个结点所指代的数组区间内的元素个数. (数组中并不一定每个位置上都有元素)
实现一个 query
的方法,该方法接受三个参数 root
, start
和 end
, 分别代表线段树的根节点和需要查询的区间,找到数组中在区间[start, end]内的元素个数。
样例:
对于数组 [0, 空,2, 3]
, 对应的线段树为:
[0, 3, count=3]
/ \
[0,1,count=1] [2,3,count=2]
/ \ / \
[0,0,count=1] [1,1,count=0] [2,2,count=1], [3,3,count=1]
query(1, 1)
, return 0
query(1, 2)
, return 1
query(2, 3)
, return 2
query(0, 2)
, return 2
思路:
主要就是边界的划分,而且注意不是每个位置都有节点,所以既要判断空,也要重新划分边界,所以在递归的时候,start取两者最大,end取两者最小。
/**
* Definition of SegmentTreeNode:
* public class SegmentTreeNode {
* public int start, end, count;
* public SegmentTreeNode left, right;
* public SegmentTreeNode(int start, int end, int count) {
* this.start = start;
* this.end = end;
* this.count = count;
* this.left = this.right = null;
* }
* }
*/
public class Solution {
/**
*@param root, start, end: The root of segment tree and
* an segment / interval
*@return: The count number in the interval [start, end]
*/
public int query(SegmentTreeNode root, int start, int end) {
// write your code here
if(root == null){
return 0;
}
if(start > end){
return 0;
}
if(root.start >= start && root.end <= end){
return root.count;
}
if(root.start <= start && root.end >= end){
if(root.left != null && root.right != null){
return query(root.left , Math.max(start,root.left.start) , Math.min(root.left.end , end))+query(root.right , Math.max(start ,root.right.start) , Math.min(end , root.right.end));
}else if(root.left != null){
return query(root.left , Math.max(start,root.left.start) , Math.min(root.left.end , end));
}else if(root.right != null){
return query(root.right , Math.max(start ,root.right.start) , Math.min(end , root.right.end));
}else{
return 0;
}
}
if(root.start >= start && root.start <=end && root.end >end){
return query(root , root.start , end);
}
if(root.end >= start && root.end <= end && root.end > start){
return query(root , start , root.end);
}
return 0;
}
}