LintCode 202. Segment Tree Query (线段树经典题!)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/roufoo/article/details/88896310
  1. Segment Tree Query
    中文English
    For an integer array (index from 0 to n-1, where n is the size of this array), in the corresponding SegmentTree, each node stores an extra attribute max to denote the maximum number in the interval of the array (index from start to end).

Design a query method with three parameters root, start and end, find the maximum number in the interval [start, end] by the given root of segment tree.

Example
For array [1, 4, 2, 3], the corresponding Segment Tree is:

              [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]
Input:query(root, 1, 1), Output:4

Input:query(root, 1, 2), Output:4

Input:query(root, 2, 3), Output:5

Input:query(root, 0, 2), Output:4
Notice
It is much easier to understand this problem if you finished Segment Tree Build first.

解法1:递归。
注意:

  1. mid必须以root->start和root->end为准,而不是start和end为准。因为线段树就是根据root->start和root->end来划分的。
  2. start和end都是与mid比较,而不是与root->start和root->end比较。
/**
 * 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: The root of segment tree.
     * @param start: start value.
     * @param end: end value.
     * @return: The maximum number in the interval [start, end]
     */
    int query(SegmentTreeNode * root, int start, int end) {
        if (!root) return 0;
        
        if (start <= root->start && end >= root->end) return root->max;
        int mid = root->start + (root->end - root->start) / 2;
        int result = 0;
        if (start <= mid) {
            result = max(result, query(root->left, start, min(mid, end)));
        }
        if (mid + 1 <= end) {
            result = max(result, query(root->right, max(mid + 1, start), end));            
        }
        
        return result;
    }
};

解法2:和解法1类似。参考九章。
区别就是这里查询的start和end一直都没变。为什么可以不变呢?因为最终递归时,比如说选左区间,如果start在左区间,end超出了左区间,那么最终左区间又会继续递归。假如start<新左区间的mid,则继续递归query start和新左区间的左区间,以及新左区间的右区间,而后者已经在[start,end]范围内。

class Solution {
public:
    /**
     * @param root: The root of segment tree.
     * @param start: start value.
     * @param end: end value.
     * @return: The maximum number in the interval [start, end]
     */
    int query(SegmentTreeNode * root, int start, int end) {
        if (!root) return 0;
        
        if (start <= root->start && end >= root->end) return root->max;
        int mid = root->start + (root->end - root->start) / 2;
        int result = 0;
        if (start <= mid) {
            result = max(result, query(root->left, start, end));
        }
        if (mid + 1 <= end) {
            result = max(result, query(root->right, start, end));            
        }
        
        return result;
    }
};

猜你喜欢

转载自blog.csdn.net/roufoo/article/details/88896310