leetcode 1157. Online Majority Element In Subarray

Implementing the class MajorityChecker, which has the following API:

  • MajorityChecker(int[] arr) constructs an instance of MajorityChecker with the given array arr;
  • int query(int left, int right, int threshold) has arguments such that:
    • 0 <= left <= right < arr.length representing a subarray of arr;
    • 2 * threshold > right - left + 1, ie. the threshold is always a strict majority of the length of the subarray

Each query(...) returns the element in arr[left], arr[left+1], ..., arr[right] that occurs at least threshold times, or -1 if no such element exists.

 

Example:

MajorityChecker majorityChecker = new MajorityChecker([1,1,2,2,1,1]);
majorityChecker.query(0,5,4); // returns 1
majorityChecker.query(0,3,3); // returns -1
majorityChecker.query(2,3,2); // returns 2

 

Constraints:

  • 1 <= arr.length <= 20000
  • 1 <= arr[i] <= 20000
  • For each query, 0 <= left <= right < len(arr)
  • For each query, 2 * threshold > right - left + 1
  • The number of queries is at most 10000

解題思路:

啥也不說了,精華全在這個題解中leetcode

方法一:線段樹

class MajorityChecker {
public:
    MajorityChecker(vector<int>& arr) :nums(arr)
    {
        tree_nodes = vector<int>(4 * arr.size() , -1) ;
        
        for(int i = 0 ; i < arr.size() ; i++) num_poses[arr[i]].push_back(i) ;
        
        build_tree(1 , 0 , nums.size() - 1) ;
    } 
    
    int query(int left, int right, int threshold) 
    {
        auto res = query(1 , 0 , nums.size() - 1 , left , right) ;
        if(res.first != -1)
        {
            if(res.second >= threshold) return res.first ;
            else return -1 ;
        }
        else return -1 ;
    }
    
    void build_tree(int node , int left , int right)
    {
        if(left == right) 
        {
            tree_nodes[node] = nums[left] ;
            return ;
        }
        
        int mid = left + (right - left) / 2 ;
        
        build_tree(2 * node , left , mid) ;
        build_tree(2 * node + 1 , mid + 1 , right) ;
        
        if(tree_nodes[2 * node] != -1 && getOccurrences(tree_nodes[2 * node] , left , right)  * 2  > right - left + 1)
        {
            tree_nodes[node] = tree_nodes[2 * node] ;
            return ;
        }
    
        if(tree_nodes[2 * node + 1] != -1 && getOccurrences(tree_nodes[2 * node + 1] , left , right) * 2 > right - left + 1)
        {
            tree_nodes[node] = tree_nodes[2 * node + 1] ;
        }
        
    }
    
    int getOccurrences(int num , int left , int right)
    {
        if(left > right) return 0 ;
        
        vector<int>& poses = num_poses[num] ;
        
        auto iter_l = lower_bound(poses.begin() , poses.end() , left) ;
        if(iter_l == poses.end()) return 0 ;
        
        auto iter_r = upper_bound(poses.begin() , poses.end() , right) ;
        return iter_r - iter_l ;
    }
    
    pair<int , int> query(int node , int left , int right , int queryl , int queryr)
    {
        if(left > queryr || right < queryl) return {-1 , -1} ;
        
        if(left >= queryl && right <= queryr) 
        {
            int num = tree_nodes[node] ;
            if(num == -1) return {-1 , -1} ;
            int cnt = getOccurrences(num , queryl , queryr) ;
            if(cnt * 2 > queryr - queryl + 1) return {num , cnt} ;
            
            return {-1 , -1} ;
        }
        
        int mid = left + (right - left) / 2 ;
        
        pair<int , int> res = query(2 * node , left , mid , queryl , queryr) ;
        if(res.first != -1) return res ;
        
        res = query(2 * node + 1 , mid + 1 , right , queryl , queryr) ;
        if(res.first != -1) return res ;
        
        return {-1 , -1} ;
    }
    
    
    
private :
    
    vector<int> nums ;
    vector<int> tree_nodes ;
    unordered_map<int , vector<int>> num_poses ;
};

/**
 * Your MajorityChecker object will be instantiated and called as such:
 * MajorityChecker* obj = new MajorityChecker(arr);
 * int param_1 = obj->query(left,right,threshold);
 */

方法二:概率

class MajorityChecker {
private:
    unordered_map<int, vector<int>> pos;
    vector<int> a;
    int try_bound;
    
public:
    MajorityChecker(vector<int>& arr): a(arr) {
        srand(time(nullptr));
        for (int i = 0; i < arr.size(); ++i) {
            pos[arr[i]].push_back(i);
        }
        try_bound = 20;
    }
    
    int get_occurrence(int num, int l, int r) {
        auto iter = pos.find(num);
        if (iter == pos.end()) {
            return 0;
        }
        const auto& vec = iter->second;
        auto iter_l = lower_bound(vec.begin(), vec.end(), l);
        if (iter_l == vec.end()) {
            return 0;
        }
        auto iter_r = upper_bound(vec.begin(), vec.end(), r);
        return iter_r - iter_l;
    }
    
    int get_random(int l, int r) {
        return rand() % (r - l + 1) + l;
    }
    
    int query(int left, int right, int threshold) {
        for (int i = 0; i < try_bound; ++i) {
            int elem = a[get_random(left, right)];
            if (get_occurrence(elem, left, right) >= threshold) {
                return elem;
            }
        }
        return -1;
    }
};
/**
 * Your MajorityChecker object will be instantiated and called as such:
 * MajorityChecker* obj = new MajorityChecker(arr);
 * int param_1 = obj->query(left,right,threshold);
 */

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章