概述:
线段树,类似区间树,是一个完全二叉树,它在各个节点保存一条线段(数组中的一段子数组),主要用于高效解决连续区间的动态查询问题,由于二叉结构的特性,它基本能保持每个操作的复杂度为O(lgN)!
性质:父亲的区间是[a,b],(c=(a+b)/2)左儿子的区间是[a,c],右儿子的区间是[c+1,b],线段树需要的空间为数组大小的四倍。
题目描述:
线段树是一棵二叉树,他的每个节点包含了两个额外的属性start和end用于表示该节点所代表的区间。start和end都是整数,并按照如下的方式赋值:
根节点的 start 和 end 由 build 方法所给出。
对于节点 A 的左儿子,有 start=A.left, end=(A.left + A.right) / 2。
对于节点 A 的右儿子,有 start=(A.left + A.right) / 2 + 1, end=A.right。
如果 start 等于 end, 那么该节点是叶子节点,不再有左右儿子。
对于给定数组设计一个build方法,构造出线段树。
说明:
wiki:
Segment Tree
Interval Tree
样例:
给出[3,2,1,4],线段树将被这样构造
[0, 3] (max = 4)
/ \
[0, 1] (max = 3) [2, 3] (max = 4)
/ \ / \
[0, 0](max = 3) [1, 1](max = 2)[2, 2](max = 1) [3, 3] (max = 4)
思路讲解:这里的思路就是跟二叉树的建立一样,运用递归的方法递归去建立,这里我们需要注意的就是关于递归的出口,我们设置的递归出口就是只有一个元素的时候即(low==high)的时候。
代码详解:
/**
* 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 A: a list of integer
* @return: The root of Segment Tree
*/
SegmentTreeNode * build(vector<int> &A) {
// write your code here
if(A.size()==0){
return NULL;
}
SegmentTreeNode *root=new SegmentTreeNode(0,0,0);
SegmentTreeNode *head=root;
BuildTree(root,A,0,A.size()-1);
return head;
}
void BuildTree(SegmentTreeNode *root,vector<int> A,int low,int high)
{
if(low<high){
int mid=(high+low)/2;
root->start=low;
root->end=high;
root->max=findmax(A,low,high);
root->left=new SegmentTreeNode(0,0,0);
BuildTree(root->left,A,low,mid);
root->right=new SegmentTreeNode(0,0,0);
BuildTree(root->right,A,mid+1,high);
}else if(low==high){
root->start=low;
root->end=high;
root->max=A[low];
}
}
int findmax(vector<int>res,int low ,int high){
int max=INT_MIN;
for(int i=low;i<=high;i++){
if(max<res[i]){
max=res[i];
}
}
return max;
}
};