LintCode线段树/扫描线/查询题总结

线段树(Segment Tree)又叫区间树(Interval Tree),它实际上是一颗二叉树,树种的每一个节点表示一个区间[a, b],左儿子的区间是[a, (a+b)/2],右儿子的区间是[(a+b)/2+1, b]

线段树常用于区间统计/查询相关的问题:比如某些数据可以按区间进行划分,按区间动态进行修改,而且还需要按区间多次进行查询,那么使用线段树可以达到较快查询速度。动态的求/更新区间和、区间最值就适用于用线段树来求解。

由于线段树的深度不会超过logL,所以查询的时间复杂度也是O(logL)。


北大的POJ上有关于这个高级数据结构的介绍:http://poj.org/summerschool/1_interval_tree.pdf

LintCode上线段树专题下有这些题目:


201. Segment Tree Build

创建线段树,利用递归的方式:

/**
 * Definition of SegmentTreeNode:
 * public class SegmentTreeNode {
 *     public int start, end;
 *     public SegmentTreeNode left, right;
 *     public SegmentTreeNode(int start, int end) {
 *         this.start = start, this.end = end;
 *         this.left = this.right = null;
 *     }
 * }
 */
public class Solution {
    /**
     *@param start, end: Denote an segment / interval
     *@return: The root of Segment Tree
     */
    public SegmentTreeNode build(int start, int end) {
        if (start <= end) {
            SegmentTreeNode node = new SegmentTreeNode(start, end);
            if (start == end) {
                return node;
            }
            node.left = build(start, (start + end) / 2);
            node.right = build( (start + end) / 2 + 1, end);
            return node;
        }
        return null;
    }
}

439. Segment Tree Build II

跟上题类似,多了一个要求,需要每个节点还要保存最大值的信息。

/**
 * Definition of SegmentTreeNode:
 * public class SegmentTreeNode {
 *     public int start, end, max;
 *     public SegmentTreeNode left, right;
 *     public SegmentTreeNode(int start, int end, int max) {
 *         this.start = start;
 *         this.end = end;
 *         this.max = max
 *         this.left = this.right = null;
 *     }
 * }
 */
public class Solution {
    /**
     *@param A: a list of integer
     *@return: The root of Segment Tree
     */
    public SegmentTreeNode buildHelper(int[] A, int start, int end) {
        if (start <= end) {
            SegmentTreeNode node = new SegmentTreeNode(start, end, A[start]);
            if (start == end) {
                return node;
            }
            node.left = buildHelper(A, start, (start + end) / 2);
            node.right = buildHelper(A, (start + end) / 2 + 1, end);
            node.max = Math.max(node.left.max, node.right.max);
            return node;
        }
        return null;
    }
    
    public SegmentTreeNode build(int[] A) {
        return buildHelper(A, 0, A.length - 1);
    }
}


202. Segment Tree Query

对线段树进行查询,要求找到给定区间(start, end)内的最大值

/**
 * Definition of SegmentTreeNode:
 * public class SegmentTreeNode {
 *     public int start, end, max;
 *     public SegmentTreeNode left, right;
 *     public SegmentTreeNode(int start, int end, int max) {
 *         this.start = start;
 *         this.end = end;
 *         this.max = max
 *         this.left = this.right = null;
 *     }
 * }
 */
public class Solution {
    /**
     *@param root, start, end: The root of segment tree and 
     *                         an segment / interval
     *@return: The maximum number in the interval [start, end]
     */
    public int query(SegmentTreeNode root, int start, int end) {
        // 查询区间在当前节点的范围之内
        if (start <= root.start && root.end <= end) {
            return root.max;
        }
        int mid = (root.start + root.end) / 2;
        int ans = Integer.MIN_VALUE;
        // 查询区间和左子树有交集
        if (start <= mid) {
            ans = Math.max(ans, query(root.left, start, end));
        }
        // 查询区间和右子树有交集
        if (end >= mid + 1) {
            ans = Math.max(ans, query(root.right, start, end));
        }
        return ans;
    }
}
<
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值