【Lintcode】202. Segment Tree Query

题目地址:

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 abm,那么就要到左子树里找 [ a , b ] [a,b] [a,b]的最大值;
3、 b ≥ a ≥ m + 1 b\ge a\ge m+1 bam+1,那么就要到右子树里找 [ a , b ] [a,b] [a,b]的最大值;
4、 a ≤ m < b a\le m<b am<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(ba)),空间 O ( log ⁡ ( x e − x s ) ) O(\log (x_e-x_s)) O(log(xexs))

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值