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
线段树,每个节点 存区间里最多出现的数并且出现次数高于区间总数量的一半,不存在则等于-1。查询时查询在此区间中,每个节点的值作为候选者,二分查找是否符合条件。
class MajorityChecker {
HashMap<Integer,ArrayList<Integer>> map;
int[] arr;
int[] tree;
public MajorityChecker(int[] arr) {
this.arr=arr;
int n=arr.length;
tree=new int[n<<2];
map=new HashMap<>();
for(int i=0;i<arr.length;i++){
int v=arr[i];
if(map.get(v)==null){
map.put(v,new ArrayList<>());
}
map.get(v).add(i);
}
build(0,n-1,1);
}
int build(int l,int r,int p){
if(l==r){
tree[p]=arr[l];
return arr[l];
}
int m=(l+r)/2;
int num1=build(l,m,p<<1);
int num2=build(m+1,r,(p<<1)+1);
if(num1!=-1){
int v=search(num1,r+1)-search(num1,l);
if(2*v>r-l+1){
tree[p]=num1;
return num1;
}
}
if(num2!=-1){
int v=search(num2,r+1)-search(num2,l);
if(2*v>r-l+1){
tree[p]=num2;
return num2;
}
}
tree[p]=-1;
return -1;
}
int search(int num,int index){
ArrayList<Integer> list=map.get(num);
int l=0,r=list.size();
while(l<r){
int m=(l+r)/2;
if(list.get(m)<index){
l=m+1;
}else{
r=m;
}
}
return l;
}
public int query(int s, int e, int threshold) {
return query(s,e,0,arr.length-1,1,threshold);
}
int query(int s,int e,int l,int r,int p,int threshold){
if(s<=l&&r<=e){
int num=tree[p];
if(num!=-1&&search(num,e+1)-search(num,s)>=threshold){
return num;
}
return -1;
}
int m=(l+r)/2;
if(s<=m){
int num1=query(s,e,l,m,p<<1,threshold);
if(num1!=-1) return num1;
}
if(e>m){
int num2=query(s,e,m+1,r,(p<<1)+1,threshold);
if(num2!=-1) return num2;
}
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);
*/