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
思路:神奇的题目,一开始想套用running sum求majority number那一套,最坏时间复杂度10000*20000,同时也会MLE
class MajorityChecker(object):
def __init__(self, arr):
"""
:type arr: List[int]
"""
self.memo={}
self.arr = arr
def query(self, left, right, threshold):
"""
:type left: int
:type right: int
:type threshold: int
:rtype: int
"""
if left in self.memo:
if right not in self.memo[left]: return -1
if self.memo[left][right][1]<threshold: return -1
return self.memo[left][right][0]
a = self.arr
f = 1
var = a[left]
count = {a[left]:1}
self.memo[left] = {left:(a[left],1)}
i=left+1
while i<=len(a)-1:
count[a[i]] = count.get(a[i],0)+1
if a[i]==var: f+=1
else: f-=1
if f!=0:
self.memo[left][i]=(var, count[var])
i+=1
else:
if i+1<=len(a)-1:
f=1
var=a[i+1]
count[a[i+1]] = count.get(a[i+1],0)+1
self.memo[left][i+1]=(var, count[var])
i+=2
if right not in self.memo[left]: return -1
if self.memo[left][right][1]<threshold: return -1
return self.memo[left][right][0]
# Your MajorityChecker object will be instantiated and called as such:
majorityChecker = MajorityChecker([1,1,2,2,1,1])
print(majorityChecker.query(0,5,4))
print(majorityChecker.query(0,3,3))
print(majorityChecker.query(2,3,2))
Discussion里的正解是random选择[left,right]区间某个数,因为如果有majority,数目一定超过一半(2 * threshold > right - left + 1
),被sample到的概率很大。然后二分搜索该element下index的上下界
比如随机选20次,一次都没选到majority的概率为(1/2)^20
import random
import bisect
class MajorityChecker(object):
def __init__(self, arr):
"""
:type arr: List[int]
"""
self.arr = arr
self.elem2index={}
for i,v in enumerate(arr):
if v not in self.elem2index: self.elem2index[v]=[]
self.elem2index[v].append(i)
def query(self, left, right, threshold):
"""
:type left: int
:type right: int
:type threshold: int
:rtype: int
"""
for _ in range(20):
a = self.arr[random.randint(left,right)]
indexes = self.elem2index[a]
l = bisect.bisect_left(indexes, left)
r = bisect.bisect_right(indexes, right)
if r-l>=threshold: return a
return -1