Skip to content

Commit 5782c1a

Browse files
authored
feat: add solutions to lc problem: No.2080 (doocs#2758)
No.2080.Range Frequency Queries
1 parent 847276b commit 5782c1a

File tree

7 files changed

+248
-122
lines changed

7 files changed

+248
-122
lines changed

solution/2000-2099/2080.Range Frequency Queries/README.md

+86-41
Original file line numberDiff line numberDiff line change
@@ -50,22 +50,28 @@ rangeFreqQuery.query(0, 11, 33); // 返回 2 。33 在整个子数组中出现 2
5050

5151
## 解法
5252

53-
### 方法一
53+
### 方法一:哈希表
54+
55+
我们用一个哈希表 $g$ 来存储每个值对应的下标数组。在构造函数中,我们遍历数组 $\text{arr}$,将每个值对应的下标加入到哈希表中。
56+
57+
在查询函数中,我们首先判断哈希表中是否存在给定的值。如果不存在,说明该值在数组中不存在,直接返回 $0$。否则,我们获取该值对应的下标数组 $\text{idx}$。然后我们使用二分查找找到下标数组中第一个大于等于 $\text{left}$ 的下标 $l$,以及第一个大于 $\text{right}$ 的下标 $r$。最后返回 $r - l$ 即可。
58+
59+
时间复杂度方面,构造函数的时间复杂度为 $O(n)$,查询函数的时间复杂度为 $O(\log n)$。其中 $n$ 为数组的长度。空间复杂度为 $O(n)$。
5460

5561
<!-- tabs:start -->
5662

5763
```python
5864
class RangeFreqQuery:
65+
5966
def __init__(self, arr: List[int]):
60-
self.mp = defaultdict(list)
67+
self.g = defaultdict(list)
6168
for i, x in enumerate(arr):
62-
self.mp[x].append(i)
69+
self.g[x].append(i)
6370

6471
def query(self, left: int, right: int, value: int) -> int:
65-
if value not in self.mp:
66-
return 0
67-
arr = self.mp[value]
68-
l, r = bisect_right(arr, left - 1), bisect_right(arr, right)
72+
idx = self.g[value]
73+
l = bisect_left(idx, left)
74+
r = bisect_left(idx, right + 1)
6975
return r - l
7076

7177

@@ -76,36 +82,25 @@ class RangeFreqQuery:
7682

7783
```java
7884
class RangeFreqQuery {
79-
private Map<Integer, List<Integer>> mp = new HashMap<>();
85+
private Map<Integer, List<Integer>> g = new HashMap<>();
8086

8187
public RangeFreqQuery(int[] arr) {
8288
for (int i = 0; i < arr.length; ++i) {
83-
mp.computeIfAbsent(arr[i], k -> new ArrayList<>()).add(i);
89+
g.computeIfAbsent(arr[i], k -> new ArrayList<>()).add(i);
8490
}
8591
}
8692

8793
public int query(int left, int right, int value) {
88-
if (!mp.containsKey(value)) {
94+
if (!g.containsKey(value)) {
8995
return 0;
9096
}
91-
List<Integer> arr = mp.get(value);
92-
int l = search(arr, left - 1);
93-
int r = search(arr, right);
97+
var idx = g.get(value);
98+
int l = Collections.binarySearch(idx, left);
99+
l = l < 0 ? -l - 1 : l;
100+
int r = Collections.binarySearch(idx, right + 1);
101+
r = r < 0 ? -r - 1 : r;
94102
return r - l;
95103
}
96-
97-
private int search(List<Integer> arr, int val) {
98-
int left = 0, right = arr.size();
99-
while (left < right) {
100-
int mid = (left + right) >> 1;
101-
if (arr.get(mid) > val) {
102-
right = mid;
103-
} else {
104-
left = mid + 1;
105-
}
106-
}
107-
return left;
108-
}
109104
}
110105

111106
/**
@@ -118,19 +113,24 @@ class RangeFreqQuery {
118113
```cpp
119114
class RangeFreqQuery {
120115
public:
121-
unordered_map<int, vector<int>> mp;
122116
RangeFreqQuery(vector<int>& arr) {
123-
for (int i = 0; i < arr.size(); ++i)
124-
mp[arr[i]].push_back(i);
117+
for (int i = 0; i < arr.size(); ++i) {
118+
g[arr[i]].push_back(i);
119+
}
125120
}
126121

127122
int query(int left, int right, int value) {
128-
if (!mp.count(value)) return 0;
129-
auto& arr = mp[value];
130-
auto l = upper_bound(arr.begin(), arr.end(), left - 1);
131-
auto r = upper_bound(arr.begin(), arr.end(), right);
123+
if (!g.contains(value)) {
124+
return 0;
125+
}
126+
auto& idx = g[value];
127+
auto l = lower_bound(idx.begin(), idx.end(), left);
128+
auto r = lower_bound(idx.begin(), idx.end(), right + 1);
132129
return r - l;
133130
}
131+
132+
private:
133+
unordered_map<int, vector<int>> g;
134134
};
135135

136136
/**
@@ -142,22 +142,24 @@ public:
142142

143143
```go
144144
type RangeFreqQuery struct {
145-
mp map[int][]int
145+
g map[int][]int
146146
}
147147

148148
func Constructor(arr []int) RangeFreqQuery {
149-
mp := make(map[int][]int)
149+
g := make(map[int][]int)
150150
for i, v := range arr {
151-
mp[v] = append(mp[v], i)
151+
g[v] = append(g[v], i)
152152
}
153-
return RangeFreqQuery{mp}
153+
return RangeFreqQuery{g}
154154
}
155155

156156
func (this *RangeFreqQuery) Query(left int, right int, value int) int {
157-
arr := this.mp[value]
158-
l := sort.SearchInts(arr, left)
159-
r := sort.SearchInts(arr, right+1)
160-
return r - l
157+
if idx, ok := this.g[value]; ok {
158+
l := sort.SearchInts(idx, left)
159+
r := sort.SearchInts(idx, right+1)
160+
return r - l
161+
}
162+
return 0
161163
}
162164

163165
/**
@@ -167,6 +169,49 @@ func (this *RangeFreqQuery) Query(left int, right int, value int) int {
167169
*/
168170
```
169171

172+
```ts
173+
class RangeFreqQuery {
174+
private g: Map<number, number[]> = new Map();
175+
176+
constructor(arr: number[]) {
177+
for (let i = 0; i < arr.length; ++i) {
178+
if (!this.g.has(arr[i])) {
179+
this.g.set(arr[i], []);
180+
}
181+
this.g.get(arr[i])!.push(i);
182+
}
183+
}
184+
185+
query(left: number, right: number, value: number): number {
186+
const idx = this.g.get(value);
187+
if (!idx) {
188+
return 0;
189+
}
190+
const search = (x: number): number => {
191+
let [l, r] = [0, idx.length];
192+
while (l < r) {
193+
const mid = (l + r) >> 1;
194+
if (idx[mid] >= x) {
195+
r = mid;
196+
} else {
197+
l = mid + 1;
198+
}
199+
}
200+
return l;
201+
};
202+
const l = search(left);
203+
const r = search(right + 1);
204+
return r - l;
205+
}
206+
}
207+
208+
/**
209+
* Your RangeFreqQuery object will be instantiated and called as such:
210+
* var obj = new RangeFreqQuery(arr)
211+
* var param_1 = obj.query(left,right,value)
212+
*/
213+
```
214+
170215
<!-- tabs:end -->
171216

172217
<!-- end -->

solution/2000-2099/2080.Range Frequency Queries/README_EN.md

+86-41
Original file line numberDiff line numberDiff line change
@@ -47,22 +47,28 @@ rangeFreqQuery.query(0, 11, 33); // return 2. The value 33 occurs 2 times in the
4747

4848
## Solutions
4949

50-
### Solution 1
50+
### Solution 1: Hash Table
51+
52+
We use a hash table $g$ to store the array of indices corresponding to each value. In the constructor, we traverse the array $\text{arr}$, adding the index corresponding to each value to the hash table.
53+
54+
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 $\text{idx}$ corresponding to the value. Then we use binary search to find the first index $l$ that is greater than or equal to $\text{left}$, and the first index $r$ that is greater than $\text{right}$. Finally, we return $r - l$.
55+
56+
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.
5157

5258
<!-- tabs:start -->
5359

5460
```python
5561
class RangeFreqQuery:
62+
5663
def __init__(self, arr: List[int]):
57-
self.mp = defaultdict(list)
64+
self.g = defaultdict(list)
5865
for i, x in enumerate(arr):
59-
self.mp[x].append(i)
66+
self.g[x].append(i)
6067

6168
def query(self, left: int, right: int, value: int) -> int:
62-
if value not in self.mp:
63-
return 0
64-
arr = self.mp[value]
65-
l, r = bisect_right(arr, left - 1), bisect_right(arr, right)
69+
idx = self.g[value]
70+
l = bisect_left(idx, left)
71+
r = bisect_left(idx, right + 1)
6672
return r - l
6773

6874

@@ -73,36 +79,25 @@ class RangeFreqQuery:
7379

7480
```java
7581
class RangeFreqQuery {
76-
private Map<Integer, List<Integer>> mp = new HashMap<>();
82+
private Map<Integer, List<Integer>> g = new HashMap<>();
7783

7884
public RangeFreqQuery(int[] arr) {
7985
for (int i = 0; i < arr.length; ++i) {
80-
mp.computeIfAbsent(arr[i], k -> new ArrayList<>()).add(i);
86+
g.computeIfAbsent(arr[i], k -> new ArrayList<>()).add(i);
8187
}
8288
}
8389

8490
public int query(int left, int right, int value) {
85-
if (!mp.containsKey(value)) {
91+
if (!g.containsKey(value)) {
8692
return 0;
8793
}
88-
List<Integer> arr = mp.get(value);
89-
int l = search(arr, left - 1);
90-
int r = search(arr, right);
94+
var idx = g.get(value);
95+
int l = Collections.binarySearch(idx, left);
96+
l = l < 0 ? -l - 1 : l;
97+
int r = Collections.binarySearch(idx, right + 1);
98+
r = r < 0 ? -r - 1 : r;
9199
return r - l;
92100
}
93-
94-
private int search(List<Integer> arr, int val) {
95-
int left = 0, right = arr.size();
96-
while (left < right) {
97-
int mid = (left + right) >> 1;
98-
if (arr.get(mid) > val) {
99-
right = mid;
100-
} else {
101-
left = mid + 1;
102-
}
103-
}
104-
return left;
105-
}
106101
}
107102

108103
/**
@@ -115,19 +110,24 @@ class RangeFreqQuery {
115110
```cpp
116111
class RangeFreqQuery {
117112
public:
118-
unordered_map<int, vector<int>> mp;
119113
RangeFreqQuery(vector<int>& arr) {
120-
for (int i = 0; i < arr.size(); ++i)
121-
mp[arr[i]].push_back(i);
114+
for (int i = 0; i < arr.size(); ++i) {
115+
g[arr[i]].push_back(i);
116+
}
122117
}
123118

124119
int query(int left, int right, int value) {
125-
if (!mp.count(value)) return 0;
126-
auto& arr = mp[value];
127-
auto l = upper_bound(arr.begin(), arr.end(), left - 1);
128-
auto r = upper_bound(arr.begin(), arr.end(), right);
120+
if (!g.contains(value)) {
121+
return 0;
122+
}
123+
auto& idx = g[value];
124+
auto l = lower_bound(idx.begin(), idx.end(), left);
125+
auto r = lower_bound(idx.begin(), idx.end(), right + 1);
129126
return r - l;
130127
}
128+
129+
private:
130+
unordered_map<int, vector<int>> g;
131131
};
132132

133133
/**
@@ -139,22 +139,24 @@ public:
139139

140140
```go
141141
type RangeFreqQuery struct {
142-
mp map[int][]int
142+
g map[int][]int
143143
}
144144

145145
func Constructor(arr []int) RangeFreqQuery {
146-
mp := make(map[int][]int)
146+
g := make(map[int][]int)
147147
for i, v := range arr {
148-
mp[v] = append(mp[v], i)
148+
g[v] = append(g[v], i)
149149
}
150-
return RangeFreqQuery{mp}
150+
return RangeFreqQuery{g}
151151
}
152152

153153
func (this *RangeFreqQuery) Query(left int, right int, value int) int {
154-
arr := this.mp[value]
155-
l := sort.SearchInts(arr, left)
156-
r := sort.SearchInts(arr, right+1)
157-
return r - l
154+
if idx, ok := this.g[value]; ok {
155+
l := sort.SearchInts(idx, left)
156+
r := sort.SearchInts(idx, right+1)
157+
return r - l
158+
}
159+
return 0
158160
}
159161

160162
/**
@@ -164,6 +166,49 @@ func (this *RangeFreqQuery) Query(left int, right int, value int) int {
164166
*/
165167
```
166168

169+
```ts
170+
class RangeFreqQuery {
171+
private g: Map<number, number[]> = new Map();
172+
173+
constructor(arr: number[]) {
174+
for (let i = 0; i < arr.length; ++i) {
175+
if (!this.g.has(arr[i])) {
176+
this.g.set(arr[i], []);
177+
}
178+
this.g.get(arr[i])!.push(i);
179+
}
180+
}
181+
182+
query(left: number, right: number, value: number): number {
183+
const idx = this.g.get(value);
184+
if (!idx) {
185+
return 0;
186+
}
187+
const search = (x: number): number => {
188+
let [l, r] = [0, idx.length];
189+
while (l < r) {
190+
const mid = (l + r) >> 1;
191+
if (idx[mid] >= x) {
192+
r = mid;
193+
} else {
194+
l = mid + 1;
195+
}
196+
}
197+
return l;
198+
};
199+
const l = search(left);
200+
const r = search(right + 1);
201+
return r - l;
202+
}
203+
}
204+
205+
/**
206+
* Your RangeFreqQuery object will be instantiated and called as such:
207+
* var obj = new RangeFreqQuery(arr)
208+
* var param_1 = obj.query(left,right,value)
209+
*/
210+
```
211+
167212
<!-- tabs:end -->
168213

169214
<!-- end -->

0 commit comments

Comments
 (0)