【Lintcode】247. Segment Tree Query II

题目地址:

https://www.lintcode.com/problem/segment-tree-query-ii/description

对于一个数组,建一棵线段树,存储这个数组在某个区间 [ x s , x e ] [x_s,x_e] [xs,xe]的元素个数(假设这个数组的范围都含在这个区间里了)。再给定一个区间 [ a , b ] [a,b] [a,b],问该数组在这个区间有多少个数。

思路是分治法。设树根维护的是 [ 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、两个区间没有交集,则返回 0 0 0
2、 a ≤ x s , b ≥ x e a\le x_s,b\ge x_e axs,bxe,那么直接返回树根维护的个数即可;
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 count number in the interval [start, end]
     */
    public int query(SegmentTreeNode root, int start, int end) {
        // write your code here
        if (root == null || end < root.start || start > root.end) {
            return 0;
        }
        
        if (start <= root.start && end >= root.end) {
            return root.count;
        }
        
        int mid = root.start + (root.end - root.start >> 1);
        if (end <= mid) {
            return query(root.left, start, end);
        }
        
        if (mid < start) {
            return query(root.right, start, end);
        }
        
        return query(root.left, start, mid) + query(root.right, mid + 1, end);
    }
}

class SegmentTreeNode {
    int start, end, count;
    SegmentTreeNode left, right;
    
    public SegmentTreeNode(int start, int end, int count) {
        this.start = start;
        this.end = end;
        this.count = count;
    }
}

时间复杂度 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))(可以参考https://blog.csdn.net/qq_46105170/article/details/108414631)。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值