lintcode
假设对于root
来说的中间分界点为rmid=(rstart+rend)/2
,关键是要找到start
、end
和中间分界点rmid
的关系以及相应的处理方法。
如果start
和end
都小于等于rmid
,那就在root->left
那边继续查询
如果start
和 end
都大于rmid
, 那就在 root->right
那边继续查询
如果start
小于等于 rmid
且 end
大于 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->left
和root->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));
}
};