Implementing the class MajorityChecker
, which has the following API:
MajorityChecker(int[] arr)
constructs an instance of MajorityChecker with the given arrayarr
;int query(int left, int right, int threshold)
has arguments such that:0 <= left <= right < arr.length
representing a subarray ofarr
;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
Solution 0: Brute Force TLE
For each range, find the majority element in O(n) time / O(n) or O(1) space.
Solution 1: Cache the range result
Cache the result for each range: mode and frequency
Time complexity:
init: O(1)
query: O(|right – left|)
total queries: O(sum(right_i – left_i)), right_i, left_i are bounds of unique ranges.
Space complexity:
init: O(1)
query: O(20000)
C++
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
// Author: Huahua, 568ms, 39.6 MB class MajorityChecker { public: MajorityChecker(vector<int>& arr):nums(arr) {} int query(int left, int right, int threshold) { int key = left * 20000 + right; if (!seen.count(key)) { int c[20001] = {0}; int best = (right - left) / 2; int best_num = -1; for (int i = left; i <= right; ++i) { if (++c[nums[i]] > best) { best = c[nums[i]]; best_num = nums[i]; } } seen[key] = {best_num, best}; } return seen[key].second >= threshold ? seen[key].first : -1; } private: unordered_map<int, pair<int, int>> seen; const vector<int>& nums; }; |
Solution 2: HashTable + binary search
Preprocessing: use a hashtable to store the indices of each element. And sort by frequency of the element in descending order.
Query: iterator over (total_freq, num) pair, if freq >= threshold do a binary search to find the frequency of the given range for num in O(logn).
Time complexity:
Init: O(nlogn)
Query: worst case: O(nlogn), best case: O(logn)
C++
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
// Author: Huahua, 156 ms, 44.7MB class MajorityChecker { public: MajorityChecker(vector<int>& arr):nums(arr) { const int max_n = *max_element(begin(nums), end(nums)); m = vector<vector<int>>(max_n + 1); for (int i = 0; i < nums.size(); ++i) m[nums[i]].push_back(i); for (int n = 1; n <= max_n; ++n) { if (m[n].size()) f.emplace_back(m[n].size(), n); } sort(rbegin(f), rend(f)); } int query(int left, int right, int threshold) { for (const auto& p : f) { if (p.first < threshold) return -1; int n = p.second; const auto& idx = m[n]; int count = upper_bound(begin(idx), end(idx), right) - lower_bound(begin(idx), end(idx), left); if (count >= threshold) return n; } return -1; } private: const vector<int>& nums; vector<vector<int>> m; // num -> {indices} vector<pair<int, int>> f; // {freq, num} }; |
Solution 2+: Randomization
Randomly pick a num in range [left, right] and check its freq, try k (e.g. 30) times. If a majority element exists, you should find it with error rate 1/2^k.
Time complexity:
Init: O(n)
Query: O(30 * logn)
Space complexity: O(n)
C++
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
// Author: Huahua, 240ms, 45.6MB class MajorityChecker { public: MajorityChecker(vector<int>& arr):nums(arr) { for (int i = 0; i < nums.size(); ++i) m[nums[i]].push_back(i); } int query(int left, int right, int threshold) { for (int i = 0; i < 30; ++i) { int n = nums[rand() % (right - left + 1) + left]; const auto& idx = m[n]; int count = upper_bound(begin(idx), end(idx), right) - lower_bound(begin(idx), end(idx), left); if (count >= threshold) return n; } return -1; } private: unordered_map<int, vector<int>> m; // num -> {indices} const vector<int>& nums; }; |
请尊重作者的劳动成果,转载请注明出处!花花保留对文章/视频的所有权利。
如果您喜欢这篇文章/视频,欢迎您捐赠花花。
If you like my articles / videos, donations are welcome.
Be First to Comment