zoukankan      html  css  js  c++  java
  • lintcode---线段树查询||(区间元素个数)

    对于一个数组,我们可以对其建立一棵 线段树, 每个结点存储一个额外的值 count 来代表这个结点所指代的数组区间内的元素个数. (数组中并不一定每个位置上都有元素)

    实现一个 query 的方法,该方法接受三个参数 root, start 和 end, 分别代表线段树的根节点和需要查询的区间,找到数组中在区间[start, end]内的元素个数。

     注意事项

    It is much easier to understand this problem if you finished Segment Tree Buildand Segment Tree Queryfirst.

    样例

    对于数组 [0, 空,2, 3], 对应的线段树为:

                         [0, 3, count=3]
                         /             
              [0,1,count=1]             [2,3,count=2]
              /                        /            
       [0,0,count=1] [1,1,count=0] [2,2,count=1], [3,3,count=1]
    

    query(1, 1), return 0

    query(1, 2), return 1

    query(2, 3), return 2

    query(0, 2), return 2

    思路:首先理解线段树,弄清要解决的问题。

         当遇到一些关于对连续点的修改和统计的问题时,可以考虑用线段树来解决。
         
    这里题目要求找到数组中在区间[start, end]内的元素个数,其实就是对连续点的统计,所以可用线段树来求解。
              
         要用递归求解,所以先要分析出基准情形,然后递归调用;要利用线段树的性质,采用二分法判断,逐步递归调用。

    思路理清楚,代码很简单:

    /**
     * Definition of SegmentTreeNode:
     * 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, start, end: The root of segment tree and 
         *                         an segment / interval
         *@return: The count number in the interval [start, end] 
         */
         
        /*
        思路:当遇到一些关于对连续点的修改和统计的问你题时,可以考虑用线段树来解决。
              这里题目要求找到数组中在区间[start, end]内的元素个数,其实就是对连续点的统计,所以可用线段树来求解。
              
              要用递归求解,所以先要分析出基准情形,然后递归调用;
        */
        int query(SegmentTreeNode *root, int start, int end) {
            // write your code here
            
            //若根节点为空或者区间不符合要求return 0;
            if(!root||start>end){
                return 0;
            }
            
            //特殊情况:如果所要求的区间范围包含了节点的区间范围,直接返回count
            if(start<=root->start&&end>=root->end){
                return root->count;
            }
            
            //一般情况,利用二分法来判断;
            int mid=root->start+(root->end-root->start)/2;
            
            
            if(start>mid){
                //情况1:如果所要求的区间在右半部分;
                return query(root->right,start,end);
            }
            else if(end<mid+1){
                //情况2:如果所要求的区间在左半部分;
                return query(root->left,start,end);
            }
                //情况3:如果所要求的区间左右两半部分,也就是利用线段树的求和性质;
            else return query(root->left,start,mid)+query(root->right,mid+1,end);
        }
    };
    
  • 相关阅读:
    修改 cmd 控制台字体、巧用 FontLink 使中英文独立设置
    非常棒的 「Sublime Text 配色/主题」与「编程字体」
    如何优雅地制作精排 ePub —— 个人电子书制作规范及基本样式表
    Simofox 2.7
    轻松绕过极域电子教室、和教师控制 Say GoodBye
    linux常用的命令
    Java Map按键(Key)排序和按值(Value)排序
    关于递归的理解以及实例
    如何去掉list里重复的数据
    快速排序的白话理解(拷贝)
  • 原文地址:https://www.cnblogs.com/Allen-rg/p/7085448.html
Copyright © 2011-2022 走看看