Skip to content

Commit 0ae1f13

Browse files
authored
feat: add solutions to lcci problem: No.10.10 (#2700)
No.10.10.Rank from Stream
1 parent ae59d0d commit 0ae1f13

File tree

7 files changed

+246
-170
lines changed

7 files changed

+246
-170
lines changed

lcci/10.10.Rank from Stream/README.md

Lines changed: 83 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -33,45 +33,37 @@
3333

3434
### 方法一:树状数组
3535

36-
树状数组,也称作“二叉索引树”(Binary Indexed Tree)或 Fenwick 树。 它可以高效地实现如下两个操作:
36+
我们可以使用树状数组维护添加过的数字中,有多少个数字小于等于当前数字。
3737

38-
1. **单点更新** `update(x, delta)`: 把序列 x 位置的数加上一个值 delta;
39-
1. **前缀和查询** `query(x)`:查询序列 `[1,...x]` 区间的区间和,即位置 x 的前缀和。
38+
我们创建一个长度为 $50010$ 的树状数组,对于 `track` 方法,我们将当前数字加一,添加到树状数组中,对于 `getRankOfNumber` 方法,我们直接查询树状数组中小于等于 $x + 1$ 的数字个数。
4039

41-
这两个操作的时间复杂度均为 $O(\log n)$。
42-
43-
树状数组最基本的功能就是求比某点 x 小的点的个数(这里的比较是抽象的概念,可以是数的大小、坐标的大小、质量的大小等等)。
44-
45-
比如给定数组 `a[5] = {2, 5, 3, 4, 1}`,求 `b[i] = 位置 i 左边小于等于 a[i] 的数的个数`。对于此例,`b[5] = {0, 1, 1, 2, 0}`
46-
47-
解决方案是直接遍历数组,每个位置先求出 `query(a[i])`,然后再修改树状数组 `update(a[i], 1)` 即可。当数的范围比较大时,需要进行离散化,即先进行去重并排序,然后对每个数字进行编号。
40+
时间复杂度方面,树状数组的更新和查询操作的时间复杂度均为 $O(\log n)$,其中 $n$ 为树状数组的长度。
4841

4942
<!-- tabs:start -->
5043

5144
```python
5245
class BinaryIndexedTree:
53-
def __init__(self, n):
46+
__slots__ = "n", "c"
47+
48+
def __init__(self, n: int):
5449
self.n = n
5550
self.c = [0] * (n + 1)
5651

57-
@staticmethod
58-
def lowbit(x):
59-
return x & -x
60-
61-
def update(self, x, delta):
52+
def update(self, x: int, delta: int) -> None:
6253
while x <= self.n:
6354
self.c[x] += delta
64-
x += BinaryIndexedTree.lowbit(x)
55+
x += x & -x
6556

66-
def query(self, x):
57+
def query(self, x: int) -> int:
6758
s = 0
68-
while x > 0:
59+
while x:
6960
s += self.c[x]
70-
x -= BinaryIndexedTree.lowbit(x)
61+
x -= x & -x
7162
return s
7263

7364

7465
class StreamRank:
66+
7567
def __init__(self):
7668
self.tree = BinaryIndexedTree(50010)
7769

@@ -95,35 +87,29 @@ class BinaryIndexedTree {
9587

9688
public BinaryIndexedTree(int n) {
9789
this.n = n;
98-
c = new int[n + 1];
99-
}
100-
101-
public static int lowbit(int x) {
102-
return x & -x;
90+
this.c = new int[n + 1];
10391
}
10492

10593
public void update(int x, int delta) {
106-
while (x <= n) {
94+
for (; x <= n; x += x & -x) {
10795
c[x] += delta;
108-
x += lowbit(x);
10996
}
11097
}
11198

11299
public int query(int x) {
113100
int s = 0;
114-
while (x > 0) {
101+
for (; x > 0; x -= x & -x) {
115102
s += c[x];
116-
x -= lowbit(x);
117103
}
118104
return s;
119105
}
120106
}
121107

122108
class StreamRank {
123-
private BinaryIndexedTree tree;
109+
private BinaryIndexedTree tree = new BinaryIndexedTree(50010);
124110

125111
public StreamRank() {
126-
tree = new BinaryIndexedTree(50010);
112+
127113
}
128114

129115
public void track(int x) {
@@ -145,41 +131,33 @@ class StreamRank {
145131

146132
```cpp
147133
class BinaryIndexedTree {
148-
public:
134+
private:
149135
int n;
150136
vector<int> c;
151137

152-
BinaryIndexedTree(int _n)
153-
: n(_n)
154-
, c(_n + 1) {}
138+
public:
139+
BinaryIndexedTree(int n)
140+
: n(n)
141+
, c(n + 1) {}
155142

156143
void update(int x, int delta) {
157-
while (x <= n) {
144+
for (; x <= n; x += x & -x) {
158145
c[x] += delta;
159-
x += lowbit(x);
160146
}
161147
}
162148

163149
int query(int x) {
164150
int s = 0;
165-
while (x > 0) {
151+
for (; x > 0; x -= x & -x) {
166152
s += c[x];
167-
x -= lowbit(x);
168153
}
169154
return s;
170155
}
171-
172-
int lowbit(int x) {
173-
return x & -x;
174-
}
175156
};
176157

177158
class StreamRank {
178159
public:
179-
BinaryIndexedTree* tree;
180-
181160
StreamRank() {
182-
tree = new BinaryIndexedTree(50010);
183161
}
184162

185163
void track(int x) {
@@ -189,6 +167,9 @@ public:
189167
int getRankOfNumber(int x) {
190168
return tree->query(x + 1);
191169
}
170+
171+
private:
172+
BinaryIndexedTree* tree = new BinaryIndexedTree(50010);
192173
};
193174

194175
/**
@@ -205,27 +186,20 @@ type BinaryIndexedTree struct {
205186
c []int
206187
}
207188
208-
func newBinaryIndexedTree(n int) *BinaryIndexedTree {
209-
c := make([]int, n+1)
210-
return &BinaryIndexedTree{n, c}
211-
}
212-
213-
func (this *BinaryIndexedTree) lowbit(x int) int {
214-
return x & -x
189+
func NewBinaryIndexedTree(n int) *BinaryIndexedTree {
190+
return &BinaryIndexedTree{n: n, c: make([]int, n+1)}
215191
}
216192
217-
func (this *BinaryIndexedTree) update(x, delta int) {
218-
for x <= this.n {
219-
this.c[x] += delta
220-
x += this.lowbit(x)
193+
func (bit *BinaryIndexedTree) update(x, delta int) {
194+
for ; x <= bit.n; x += x & -x {
195+
bit.c[x] += delta
221196
}
222197
}
223198
224-
func (this *BinaryIndexedTree) query(x int) int {
199+
func (bit *BinaryIndexedTree) query(x int) int {
225200
s := 0
226-
for x > 0 {
227-
s += this.c[x]
228-
x -= this.lowbit(x)
201+
for ; x > 0; x -= x & -x {
202+
s += bit.c[x]
229203
}
230204
return s
231205
}
@@ -235,8 +209,7 @@ type StreamRank struct {
235209
}
236210
237211
func Constructor() StreamRank {
238-
tree := newBinaryIndexedTree(50010)
239-
return StreamRank{tree}
212+
return StreamRank{NewBinaryIndexedTree(50010)}
240213
}
241214
242215
func (this *StreamRank) Track(x int) {
@@ -255,6 +228,53 @@ func (this *StreamRank) GetRankOfNumber(x int) int {
255228
*/
256229
```
257230

231+
```ts
232+
class BinaryIndexedTree {
233+
private n: number;
234+
private c: number[];
235+
236+
constructor(n: number) {
237+
this.n = n;
238+
this.c = Array(n + 1).fill(0);
239+
}
240+
241+
update(x: number, delta: number): void {
242+
for (; x <= this.n; x += x & -x) {
243+
this.c[x] += delta;
244+
}
245+
}
246+
247+
query(x: number): number {
248+
let s = 0;
249+
for (; x > 0; x -= x & -x) {
250+
s += this.c[x];
251+
}
252+
return s;
253+
}
254+
}
255+
256+
class StreamRank {
257+
private tree: BinaryIndexedTree = new BinaryIndexedTree(50010);
258+
259+
constructor() {}
260+
261+
track(x: number): void {
262+
this.tree.update(x + 1, 1);
263+
}
264+
265+
getRankOfNumber(x: number): number {
266+
return this.tree.query(x + 1);
267+
}
268+
}
269+
270+
/**
271+
* Your StreamRank object will be instantiated and called as such:
272+
* var obj = new StreamRank()
273+
* obj.track(x)
274+
* var param_2 = obj.getRankOfNumber(x)
275+
*/
276+
```
277+
258278
<!-- tabs:end -->
259279

260280
<!-- end -->

0 commit comments

Comments
 (0)