1. 程式人生 > 實用技巧 >97 子陣列中佔絕大多數的元素(1157)

97 子陣列中佔絕大多數的元素(1157)

作者: Turbo時間限制: 1S章節: 線段樹

晚於: 2020-09-09 12:00:00後提交分數乘係數50%

問題描述 :

實現一個 MajorityChecker 的類,它具有下述兩個 API:

1、MajorityChecker(int[] arr) :用給定的陣列 arr 來構造一個 MajorityChecker 的例項。

2、int query(int left, int right, int threshold)

引數為:

0 <= left <= right < arr.length ,其中arr.length表示陣列 arr 的長度。

2 * threshold > right - left + 1,也就是說閾值 threshold 始終比子序列長度的一半還要大。

功能:每次查詢返回在 arr[left], arr[left+1], ..., arr[right] 中至少出現threshold次數的元素,如果不存在這樣的元素,就返回 -1。

說明:由於threshold比子序列長度的一半還要大,因此,不可能存在兩個元素都出現了threshold次。

示例:

MajorityChecker majorityChecker = new MajorityChecker([1,1,2,2,1,1]);

majorityChecker.query(0,5,4); // 返回 1

majorityChecker.query(0,3,3); // 返回 -1

majorityChecker.query(2,3,2); // 返回 2

可使用以下main函式:

int main()

{

int n,a,m,left,right, threshold;

vector<int> arr;

cin>>n;

for(int i=0; i<n; i++)

{

cin>>a;

arr.push_back(a);

}

MajorityChecker mc(arr);

cin>>m;

for(int i=0; i<m; i++)

{//在IDE中執行時,輸入和輸出會交錯,這是正常現象

cin>>left;

cin>>right;

cin>>threshold;

int res=mc.query(left, right, threshold) ;

cout<<res<<" ";

}

}

輸入說明 :

首先輸入arr陣列的長度n,然後輸入n個整數,表示arr中的元素

再輸入查詢的次數m,

然後輸入m行,每行是一個查詢的引數left, right, threshold,用空格分隔。

提示:

1 <= n <= 20000

1 <= arr[i] <= 20000

對於每次查詢,0 <= left <= right < n

對於每次查詢,2 * threshold > right - left + 1

m<=10000

輸出說明 :

輸出m個整數,對應m次查詢的結果,每個整數後有一個空格。

輸入範例 :

輸出範例 :

#include <iostream>
#include <string>
#include <vector>
#include <unordered_map>
#include <algorithm>
using namespace std;
class MajorityChecker {
public:
    unordered_map<int, vector<int>> map;
    
    MajorityChecker(vector<int>& arr) {
      for (auto i = 0; i < arr.size(); ++i) map[arr[i]].push_back(i);
    }
    
    int query(int left, int right, int threshold) {
      for (auto &temp : map) {
        if (temp.second.size() < threshold) continue;
        auto m= lower_bound(begin(temp.second), end(temp.second), left);
        auto n = upper_bound(begin(temp.second), end(temp.second), right);
        if (n - m >= threshold) return temp.first;
      }
      return -1;
    }
};
int main()
{
    int n,a,m,left,right, threshold;
    vector<int> arr;
    cin>>n;
    for(int i=0; i<n; i++)
    {
        cin>>a;
        arr.push_back(a);
    }
    MajorityChecker mc(arr);
    cin>>m;
    for(int i=0; i<m; i++)
    {//在IDE中執行時,輸入和輸出會交錯,這是正常現象
        cin>>left;
        cin>>right;
        cin>>threshold;
        int res=mc.query(left, right, threshold) ;
        cout<<res<<" ";
    }
}
//lower_bound(起始地址,結束地址,要查詢的數值) 返回的是數值 第一個 出現的位置。
//upper_bound(起始地址,結束地址,要查詢的數值) 返回的是數值 最後一個 出現的位置。
//binary_search(起始地址,結束地址,要查詢的數值) 返回的是是否存在這麼一個數,是一個bool值。
/*
int ia[] = {0,1,2,3,4,5,6,7,8,9};
int *beg = begin(ia);
int *last  = end(ia);
上面程式碼中begin()返回的是陣列首元素的指標,
end()返回的是尾元素的下一位置的指標。
這是C++11 為我們提供的兩個非常方便的定位陣列指標的函式。

*/