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);
    }
};

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM