题目地址:
https://www.lintcode.com/problem/segment-tree-query/description
给定一棵线段树,每个节点维护的是当前区间的最大值。给定一个区间,要求返回这个区间的最大值。题目保证这个区间包含在整棵树维护的区间之内。
思路是分治法。设树根维护的是
[
x
s
,
x
e
]
[x_s,x_e]
[xs,xe],区间中点是
m
=
x
s
+
x
e
2
m=\frac{x_s+x_e}{2}
m=2xs+xe,要求的区间是
[
a
,
b
]
[a,b]
[a,b]。分下面几个情况讨论:
1、
x
s
=
a
,
x
e
=
b
x_s=a,x_e=b
xs=a,xe=b,那么直接返回树根维护的最大值即可;
2、
a
≤
b
≤
m
a\le b\le m
a≤b≤m,那么就要到左子树里找
[
a
,
b
]
[a,b]
[a,b]的最大值;
3、
b
≥
a
≥
m
+
1
b\ge a\ge m+1
b≥a≥m+1,那么就要到右子树里找
[
a
,
b
]
[a,b]
[a,b]的最大值;
4、
a
≤
m
<
b
a\le m<b
a≤m<b,那么就要左右子树里都要找,在左子树里找
[
a
,
m
]
[a,m]
[a,m]的最大值,在右子树里找
[
m
+
1
,
b
]
[m+1,b]
[m+1,b]的最大值,然后结合起来就得到了
[
a
,
b
]
[a,b]
[a,b]的最大值。
上述四种情况都可以用递归来解决。代码如下:
public class Solution {
/**
* @param root: The root of segment tree.
* @param start: start value.
* @param end: end value.
* @return: The maximum number in the interval [start, end]
*/
public int query(SegmentTreeNode root, int start, int end) {
// write your code here
if (start == root.start && root.end == end) {
return root.max;
}
int mid = root.start + (root.end - root.start >> 1);
if (end <= mid) {
return query(root.left, start, end);
}
if (start >= mid + 1) {
return query(root.right, start, end);
}
int left = query(root.left, start, mid), right = query(root.right, mid + 1, end);
return Math.max(left, right);
}
}
class SegmentTreeNode {
int start, end, max;
SegmentTreeNode left, right;
public SegmentTreeNode(int start, int end, int max) {
this.start = start;
this.end = end;
this.max = max;
}
}
时间复杂度 O ( log ( b − a ) ) O(\log (b-a)) O(log(b−a)),空间 O ( log ( x e − x s ) ) O(\log (x_e-x_s)) O(log(xe−xs))。