Skip to content

Commit edde105

Browse files
committed
feat: add solutions to lcci problem: No.10.10
No.10.10.Rank from Stream
1 parent cc76854 commit edde105

File tree

12 files changed

+737
-67
lines changed

12 files changed

+737
-67
lines changed

lcci/10.10.Rank from Stream/README.md

+219
Original file line numberDiff line numberDiff line change
@@ -33,22 +33,241 @@
3333

3434
<!-- 这里可写通用的实现逻辑 -->
3535

36+
树状数组。
37+
38+
树状数组,也称作“二叉索引树”(Binary Indexed Tree)或 Fenwick 树。 它可以高效地实现如下两个操作:
39+
40+
1. **单点更新** `update(x, delta)`: 把序列 x 位置的数加上一个值 delta;
41+
1. **前缀和查询** `query(x)`:查询序列 `[1,...x]` 区间的区间和,即位置 x 的前缀和。
42+
43+
这两个操作的时间复杂度均为 `O(log n)`
44+
45+
树状数组最基本的功能就是求比某点 x 小的点的个数(这里的比较是抽象的概念,可以是数的大小、坐标的大小、质量的大小等等)。
46+
47+
比如给定数组 `a[5] = {2, 5, 3, 4, 1}`,求 `b[i] = 位置 i 左边小于等于 a[i] 的数的个数`。对于此例,`b[5] = {0, 1, 1, 2, 0}`
48+
49+
解决方案是直接遍历数组,每个位置先求出 `query(a[i])`,然后再修改树状数组 `update(a[i], 1)` 即可。当数的范围比较大时,需要进行离散化,即先进行去重并排序,然后对每个数字进行编号。
50+
3651
<!-- tabs:start -->
3752

3853
### **Python3**
3954

4055
<!-- 这里可写当前语言的特殊实现逻辑 -->
4156

4257
```python
58+
class BinaryIndexedTree:
59+
def __init__(self, n):
60+
self.n = n
61+
self.c = [0] * (n + 1)
62+
63+
@staticmethod
64+
def lowbit(x):
65+
return x & -x
66+
67+
def update(self, x, delta):
68+
while x <= self.n:
69+
self.c[x] += delta
70+
x += BinaryIndexedTree.lowbit(x)
71+
72+
def query(self, x):
73+
s = 0
74+
while x > 0:
75+
s += self.c[x]
76+
x -= BinaryIndexedTree.lowbit(x)
77+
return s
78+
4379

80+
class StreamRank:
81+
82+
def __init__(self):
83+
self.tree = BinaryIndexedTree(50010)
84+
85+
def track(self, x: int) -> None:
86+
self.tree.update(x + 1, 1)
87+
88+
def getRankOfNumber(self, x: int) -> int:
89+
return self.tree.query(x + 1)
90+
91+
92+
# Your StreamRank object will be instantiated and called as such:
93+
# obj = StreamRank()
94+
# obj.track(x)
95+
# param_2 = obj.getRankOfNumber(x)
4496
```
4597

4698
### **Java**
4799

48100
<!-- 这里可写当前语言的特殊实现逻辑 -->
49101

50102
```java
103+
class BinaryIndexedTree {
104+
private int n;
105+
private int[] c;
106+
107+
public BinaryIndexedTree(int n) {
108+
this.n = n;
109+
c = new int[n + 1];
110+
}
111+
112+
public static int lowbit(int x) {
113+
return x & -x;
114+
}
115+
116+
public void update(int x, int delta) {
117+
while (x <= n) {
118+
c[x] += delta;
119+
x += lowbit(x);
120+
}
121+
}
122+
123+
public int query(int x) {
124+
int s = 0;
125+
while (x > 0) {
126+
s += c[x];
127+
x -= lowbit(x);
128+
}
129+
return s;
130+
}
131+
}
132+
133+
class StreamRank {
134+
private BinaryIndexedTree tree;
135+
136+
public StreamRank() {
137+
tree = new BinaryIndexedTree(50010);
138+
}
139+
140+
public void track(int x) {
141+
tree.update(x + 1, 1);
142+
}
143+
144+
public int getRankOfNumber(int x) {
145+
return tree.query(x + 1);
146+
}
147+
}
148+
149+
/**
150+
* Your StreamRank object will be instantiated and called as such:
151+
* StreamRank obj = new StreamRank();
152+
* obj.track(x);
153+
* int param_2 = obj.getRankOfNumber(x);
154+
*/
155+
```
156+
157+
### **C++**
158+
159+
```cpp
160+
class BinaryIndexedTree {
161+
public:
162+
int n;
163+
vector<int> c;
164+
165+
BinaryIndexedTree(int _n): n(_n), c(_n + 1){}
166+
167+
void update(int x, int delta) {
168+
while (x <= n)
169+
{
170+
c[x] += delta;
171+
x += lowbit(x);
172+
}
173+
}
174+
175+
int query(int x) {
176+
int s = 0;
177+
while (x > 0)
178+
{
179+
s += c[x];
180+
x -= lowbit(x);
181+
}
182+
return s;
183+
}
184+
185+
int lowbit(int x) {
186+
return x & -x;
187+
}
188+
};
189+
190+
class StreamRank {
191+
public:
192+
BinaryIndexedTree* tree;
193+
194+
StreamRank() {
195+
tree = new BinaryIndexedTree(50010);
196+
}
197+
198+
void track(int x) {
199+
tree->update(x + 1, 1);
200+
}
201+
202+
int getRankOfNumber(int x) {
203+
return tree->query(x + 1);
204+
}
205+
};
206+
207+
/**
208+
* Your StreamRank object will be instantiated and called as such:
209+
* StreamRank* obj = new StreamRank();
210+
* obj->track(x);
211+
* int param_2 = obj->getRankOfNumber(x);
212+
*/
213+
```
214+
215+
### **Go**
216+
217+
```go
218+
type BinaryIndexedTree struct {
219+
n int
220+
c []int
221+
}
222+
223+
func newBinaryIndexedTree(n int) *BinaryIndexedTree {
224+
c := make([]int, n+1)
225+
return &BinaryIndexedTree{n, c}
226+
}
227+
228+
func (this *BinaryIndexedTree) lowbit(x int) int {
229+
return x & -x
230+
}
231+
232+
func (this *BinaryIndexedTree) update(x, delta int) {
233+
for x <= this.n {
234+
this.c[x] += delta
235+
x += this.lowbit(x)
236+
}
237+
}
238+
239+
func (this *BinaryIndexedTree) query(x int) int {
240+
s := 0
241+
for x > 0 {
242+
s += this.c[x]
243+
x -= this.lowbit(x)
244+
}
245+
return s
246+
}
247+
248+
type StreamRank struct {
249+
tree *BinaryIndexedTree
250+
}
251+
252+
func Constructor() StreamRank {
253+
tree := newBinaryIndexedTree(50010)
254+
return StreamRank{tree}
255+
}
256+
257+
func (this *StreamRank) Track(x int) {
258+
this.tree.update(x+1, 1)
259+
}
260+
261+
func (this *StreamRank) GetRankOfNumber(x int) int {
262+
return this.tree.query(x + 1)
263+
}
51264
265+
/**
266+
* Your StreamRank object will be instantiated and called as such:
267+
* obj := Constructor();
268+
* obj.Track(x);
269+
* param_2 := obj.GetRankOfNumber(x);
270+
*/
52271
```
53272

54273
### **...**

0 commit comments

Comments
 (0)