问题:
给定数组,求给定区间中,出现次数>=threshold的元素值。
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
解法:
随机值法:【参考解说】
给定一个区间,显然可以尝试从中随机选择数字,
然后判断该数字是否是该区间中的majority(需要用到Index Search Array)。
如果经过多次随机都找不到,则说明不存在majority。
通过多次随机,可以将错误概率降低到非常小,可以算是一种成功的算法。
构建一个map:coutarr
key:原数组的元素值
value:所在index(会存在多个,因此为一个vector<int>)
对于猜测的随机值value:
在map:coutarr中找到该元素值,得到元素值的所有index序列,
在这个序列中找,在给定区间(left, right)内,有多少个index。
这里使用到
auto l=lower_bound(it->second.begin(), it->second.end(), left);
auto r=upper_bound(it->second.begin(), it->second.end(), right);
在给定vector区间(it->second.begin(), it->second.end())中,
lower_bound:找到第一个值>=left的元素index返回。
upper_bound:找到第一个值>right的元素index返回。
则 r-l 即为值value在给定区间(left, right)内,出现的次数。
若这个次数>=threshold,则猜测正确。
代码参考:
1 class MajorityChecker { 2 public: 3 vector<int> arrv;//{pos,value} 4 unordered_map<int, vector<int>>coutarr; 5 int coutValue(int left, int right, int value){ 6 auto it = coutarr.find(value); 7 if(it==coutarr.end()) return 0; 8 auto l=lower_bound(it->second.begin(), it->second.end(), left); 9 auto r=upper_bound(it->second.begin(), it->second.end(), right); 10 return r-l; 11 } 12 MajorityChecker(vector<int>& arr) { 13 arrv=arr; 14 for(int i=0; i<arr.size(); i++){ 15 coutarr[arr[i]].push_back(i); 16 } 17 srand(time(0)); 18 } 19 20 int query(int left, int right, int threshold) { 21 for(int i=0; i<20; i++){ 22 int idx = random() % (right-left+1) +left; 23 int cout = coutValue(left, right, arrv[idx]); 24 if(cout>=threshold) return arrv[idx]; 25 } 26 return -1; 27 } 28 }; 29 30 /** 31 * Your MajorityChecker object will be instantiated and called as such: 32 * MajorityChecker* obj = new MajorityChecker(arr); 33 * int param_1 = obj->query(left,right,threshold); 34 */