lintcode segment-tree-query 线段树的查询

问题描述

lintcode

笔记

假设对于root来说的中间分界点为rmid=(rstart+rend)/2,关键是要找到startend和中间分界点rmid的关系以及相应的处理方法。

  • 如果startend都小于等于rmid,那就在root->left那边继续查询

  • 如果startend 都大于rmid, 那就在 root->right 那边继续查询

  • 如果start 小于等于 rmidend 大于 rmid ,那就两边都要查询,然后取较大值。

代码

/**
 * Definition of SegmentTreeNode:
 * class SegmentTreeNode {
 * public:
 *     int start, end, max;
 *     SegmentTreeNode *left, *right;
 *     SegmentTreeNode(int start, int end, int max) {
 *         this->start = start;
 *         this->end = end;
 *         this->max = max;
 *         this->left = this->right = NULL;
 *     }
 * }
 */
class Solution {
public:
    /**
     *@param root, start, end: The root of segment tree and 
     *                         an segment / interval
     *@return: The maximum number in the interval [start, end]
     */
    int query(SegmentTreeNode *root, int start, int end) {
        // write your code here
        int rstart = root->start;
        int rend = root->end;
        int rmid = (rstart + rend) / 2; 
        if (start == rstart && rend == end)
            return root->max;
        if (start <= rmid && end <= rmid)
            return query(root->left, start, end);
        if (start > rmid && end > rmid)
            return query(root->right, start, end);
        if (start <= rmid && end > rmid)
            return max(query(root->left, start, rmid), query(root->right, rmid+1, end));
    }
};

九章算法的解法

比较简洁。用到了一些技巧。不是特别理解。

  • 如果要查询的范围超出了root的范围,那就返回INT_MIN

  • 如果查询的范围完全包含了root的范围,就返回root->max

  • 否则查询root->leftroot->right

在这种设定下,只有查询范围完全包含了当前节点的范围才会返回max,那么查询范围终归会拆分成两个合适的区间,然后取max,如题目中的例子,要查询(0,2), 这个查询范围完全包含的节点范围只有(0,1)和(2,2),因此最终会返回这两者的较大值。
[0, 3, max=4]
/ \
[0,1,max=4] [2,3,max=3]
/ \ / \
[0,0,max=1] [1,1,max=4] [2,2,max=2], [3,3,max=3]

/**
 * Definition of SegmentTreeNode:
 * class SegmentTreeNode {
 * public:
 *     int start, end, max;
 *     SegmentTreeNode *left, *right;
 *     SegmentTreeNode(int start, int end, int max) {
 *         this->start = start;
 *         this->end = end;
 *         this->max = max;
 *         this->left = this->right = NULL;
 *     }
 * }
 */
class Solution {
public:
    /**
     *@param root, start, end: The root of segment tree and 
     *                         an segment / interval
     *@return: The maximum number in the interval [start, end]
     */
    int query(SegmentTreeNode *root, int start, int end) {
        // write your code here
        if (root->end < start || root->start > end) // 查询范围超出当前节点范围
            return INT_MIN;

        if (root->start >= start && root->end <= end)// 查询范围包含当前节点范围
            return root->max;

        // 查询范围既没有包含当前节点范围,也没有超出当前节点范围,那就是包含了一小部分的当前节点范围咯
        return max(query(root->left, start, end), query(root->right, start, end));

    }
};

你可能感兴趣的:(lintcode,二叉树,线段树)