线段树的构造 II-LintCode

线段树是一棵二叉树,他的每个节点包含了两个额外的属性start和end用于表示该节点所代表的区间。start和end都是整数,并按照如下的方式赋值:

  1. 根节点的 start 和 end 由 build 方法所给出。
  2. 对于节点 A 的左儿子,有 start=A.left, end=(A.left + A.right) / 2。
  3. 对于节点 A 的右儿子,有 start=(A.left + A.right) / 2 + 1, end=A.right。
  4. 如果 start 等于 end, 那么该节点是叶子节点,不再有左右儿子。

对于给定数组设计一个build方法,构造出线段树

样例:
给出[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)

思路:
对于线段树root,给定查询范围[start,end],若[start,end]超出root所表示的范围,则规范start或end的值。
若[start,end]位于当前节点node的区间内,且节点node的count值为0,则[start,end]中也不可能存在元素,返回0。
若[start,end]就是当前节点node的区间,返回node的count值。
若start大于node右子树的start值,则在node的右子树中进行查询;若end小于node的左子树的end值,则在node的左子树中进行查询;否则,在左子树中查询[start,node->left->end],右子树中查询[node->right->start,end],并取二者之和。

#ifndef C247_H
#define C247_H
#include<iostream>
using namespace std;
class SegmentTreeNode{
public:
    int start, end, count;
    SegmentTreeNode *left, *right;
    SegmentTreeNode(int start, int end, int count){
        this->start = start;
        this->end = end;
        this->count = count;
        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 count number in the interval [start, end]
    */
    int query(SegmentTreeNode *root, int start, int end) {
        // write your code here
        if (start > end || !root)
            return 0;
        //当查询范围超出当前节点范围时,规范其范围
        if (start < root->start)
            return query(root, root->start, end);
        if (end>root->end)
            return query(root, start, root->end);
        SegmentTreeNode *node = root;
        //若查询范围小于当前节点范围,且当前节点count为0,直接返回0
        if (start >= node->start&&end <= node->end&&node->count == 0)
            return 0;
        //若查询范围等于当前节点范围,返回当前节点的count值
        if (start == node->start&&end == node->end)
            return node->count;
        //根据查询范围改变搜索节点
        if (start >= node->right->start)
            return query(node->right, start, end);
        else if (end <= node->left->end)
            return query(node->left, start, end);
        else
        {
            int l = query(node->left, start, node->left->end);
            int r = query(node->right, node->right->start, end);
            return l + r;
        }
    }
};
#endif
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值