Design a data structure to find the frequency of a given value in a given subarray.
The frequency of a value in a subarray is the number of occurrences of that value in the subarray.
Implement the RangeFreqQuery class:
RangeFreqQuery(int[] arr) Constructs an instance of the class with the given 0-indexed integer array arr.
int query(int left, int right, int value) Returns the frequency of value in the subarray arr[left...right].
A subarray is a contiguous sequence of elements within an array. arr[left...right] denotes the subarray that contains the elements of nums between indices left and right (inclusive).
Example 1:
Input
["RangeFreqQuery", "query", "query"]
[[[12, 33, 4, 56, 22, 2, 34, 33, 22, 12, 34, 56]], [1, 2, 4], [0, 11, 33]]
Output
[null, 1, 2]
Explanation
RangeFreqQuery rangeFreqQuery = new RangeFreqQuery([12, 33, 4, 56, 22, 2, 34, 33, 22, 12, 34, 56]);
rangeFreqQuery.query(1, 2, 4); // return 1. The value 4 occurs 1 time in the subarray [33, 4]
rangeFreqQuery.query(0, 11, 33); // return 2. The value 33 occurs 2 times in the whole array.
Constraints:
1 <= arr.length <= 105
1 <= arr[i], value <= 104
0 <= left <= right < arr.length
At most 105 calls will be made to query
Solutions
Solution 1: Hash Table
We use a hash table $g$ to store the array of indices corresponding to each value. In the constructor, we traverse the array $\textit{arr}$, adding the index corresponding to each value to the hash table.
In the query function, we first check whether the given value exists in the hash table. If it does not exist, it means that the value does not exist in the array, so we directly return $0$. Otherwise, we get the index array $\textit{idx}$ corresponding to the value. Then we use binary search to find the first index $l$ that is greater than or equal to $\textit{left}$, and the first index $r$ that is greater than $\textit{right}$. Finally, we return $r - l$.
In terms of time complexity, the time complexity of the constructor is $O(n)$, and the time complexity of the query function is $O(\log n)$. The space complexity is $O(n)$. Where $n$ is the length of the array.
1 2 3 4 5 6 7 8 91011121314151617
classRangeFreqQuery:def__init__(self,arr:List[int]):self.g=defaultdict(list)fori,xinenumerate(arr):self.g[x].append(i)defquery(self,left:int,right:int,value:int)->int:idx=self.g[value]l=bisect_left(idx,left)r=bisect_left(idx,right+1)returnr-l# Your RangeFreqQuery object will be instantiated and called as such:# obj = RangeFreqQuery(arr)# param_1 = obj.query(left,right,value)
classRangeFreqQuery{privateMap<Integer,List<Integer>>g=newHashMap<>();publicRangeFreqQuery(int[]arr){for(inti=0;i<arr.length;++i){g.computeIfAbsent(arr[i],k->newArrayList<>()).add(i);}}publicintquery(intleft,intright,intvalue){if(!g.containsKey(value)){return0;}varidx=g.get(value);intl=Collections.binarySearch(idx,left);l=l<0?-l-1:l;intr=Collections.binarySearch(idx,right+1);r=r<0?-r-1:r;returnr-l;}}/** * Your RangeFreqQuery object will be instantiated and called as such: * RangeFreqQuery obj = new RangeFreqQuery(arr); * int param_1 = obj.query(left,right,value); */
classRangeFreqQuery{public:RangeFreqQuery(vector<int>&arr){for(inti=0;i<arr.size();++i){g[arr[i]].push_back(i);}}intquery(intleft,intright,intvalue){if(!g.contains(value)){return0;}auto&idx=g[value];autol=lower_bound(idx.begin(),idx.end(),left);autor=lower_bound(idx.begin(),idx.end(),right+1);returnr-l;}private:unordered_map<int,vector<int>>g;};/** * Your RangeFreqQuery object will be instantiated and called as such: * RangeFreqQuery* obj = new RangeFreqQuery(arr); * int param_1 = obj->query(left,right,value); */
typeRangeFreqQuerystruct{gmap[int][]int}funcConstructor(arr[]int)RangeFreqQuery{g:=make(map[int][]int)fori,v:=rangearr{g[v]=append(g[v],i)}returnRangeFreqQuery{g}}func(this*RangeFreqQuery)Query(leftint,rightint,valueint)int{ifidx,ok:=this.g[value];ok{l:=sort.SearchInts(idx,left)r:=sort.SearchInts(idx,right+1)returnr-l}return0}/** * Your RangeFreqQuery object will be instantiated and called as such: * obj := Constructor(arr); * param_1 := obj.Query(left,right,value); */
classRangeFreqQuery{privateg:Map<number,number[]>=newMap();constructor(arr:number[]){for(leti=0;i<arr.length;++i){if(!this.g.has(arr[i])){this.g.set(arr[i],[]);}this.g.get(arr[i])!.push(i);}}query(left:number,right:number,value:number):number{constidx=this.g.get(value);if(!idx){return0;}constsearch=(x:number):number=>{let[l,r]=[0,idx.length];while(l<r){constmid=(l+r)>>1;if(idx[mid]>=x){r=mid;}else{l=mid+1;}}returnl;};constl=search(left);constr=search(right+1);returnr-l;}}/** * Your RangeFreqQuery object will be instantiated and called as such: * var obj = new RangeFreqQuery(arr) * var param_1 = obj.query(left,right,value) */