Skip to content

Commit 5f3937b

Browse files
committed
✨ feat: 新增多个 LeetCode 146 题目的解法,更新相关文档链接
1 parent 8e86dad commit 5f3937b

24 files changed

+5669
-3030
lines changed

26_misc/wal/note.md

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
https://juejin.cn/post/6919298282711678989
2+
https://www.yoonper.com/post.php?id=129

6_tree/btree/B-tree Path Hints.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1+
https://github.com/tidwall/btree/issues/7
12
https://github.com/tidwall/btree/blob/master/PATH_HINT.md
2-
33
**B-tree Path Hints** 是一种针对 **B-Tree**(B 树)所做的**搜索与插入优化**技巧,通过**记录并重用上一次操作中定位到目标元素的“路径”**,来加速后续对相邻或相似键的访问。可以把它理解为一种“局部性优化”:`如果连续处理的键彼此在 B-Tree 中的位置比较接近,那么直接使用“上次找到的路径”去做下一次搜索,会比每次从头在节点里做二分查找更快。`
44

55
---

6_tree/btree/BTreeIterator.ts

+267
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,267 @@
1+
// https://github.com/tidwall/btree/blob/51838063d453a243f6c4df75c5278efba5c6ffc8/btreeg.go#L1124
2+
3+
interface IBTreeNode<T> {
4+
isLeaf(): boolean
5+
items(): T[]
6+
children(): IBTreeNode<T>[]
7+
}
8+
9+
interface IBTree<N extends IBTreeNode<T>, T> {
10+
root(): N | undefined
11+
find(node: N, item: T, depth: number): { index: number; found: boolean }
12+
}
13+
14+
class BTreeIterator<N extends IBTreeNode<T>, T> {
15+
private _tree: IBTree<N, T> | undefined
16+
17+
private readonly _stack: { node: N; index: number }[] = []
18+
private _item: T | undefined = undefined
19+
private _seeked = false
20+
private _atStart = false
21+
private _atEnd = false
22+
23+
constructor(tree: IBTree<N, T> | undefined) {
24+
this._tree = tree
25+
}
26+
27+
first(): boolean {
28+
if (!this._tree) return false
29+
this._atEnd = false
30+
this._atStart = false
31+
this._seeked = true
32+
this._stack.length = 0
33+
const root = this._tree.root()
34+
if (!root) return false
35+
36+
let node = root
37+
for (;;) {
38+
this._stack.push({ node, index: 0 })
39+
if (node.isLeaf()) {
40+
break
41+
}
42+
node = node.children()[0] as N
43+
}
44+
const s = this._stack[this._stack.length - 1]
45+
this._item = s.node.items()[s.index]
46+
return true
47+
}
48+
49+
last(): boolean {
50+
if (!this._tree) return false
51+
this._seeked = true
52+
this._stack.length = 0
53+
const root = this._tree.root()
54+
if (!root) return false
55+
56+
let node = root
57+
for (;;) {
58+
this._stack.push({ node, index: node.items().length })
59+
if (node.isLeaf()) {
60+
this._stack[this._stack.length - 1].index--
61+
break
62+
}
63+
node = node.children()[node.items().length] as N
64+
}
65+
const s = this._stack[this._stack.length - 1]
66+
this._item = s.node.items()[s.index]
67+
return true
68+
}
69+
70+
seek(item: T): boolean {
71+
if (!this._tree) return false
72+
this._seeked = true
73+
this._stack.length = 0
74+
const root = this._tree.root()
75+
if (!root) return false
76+
77+
let node = root
78+
let depth = 0
79+
for (;;) {
80+
const { index, found } = this._tree.find(node, item, depth)
81+
this._stack.push({ node, index })
82+
if (found) {
83+
this._item = node.items()[index]
84+
return true
85+
}
86+
if (node.isLeaf()) {
87+
this._stack[this._stack.length - 1].index--
88+
return this.next()
89+
}
90+
node = node.children()[index] as N
91+
depth++
92+
}
93+
}
94+
95+
prev(): boolean {
96+
if (!this._tree) return false
97+
if (!this._seeked) return false
98+
if (this._stack.length === 0) {
99+
if (this._atEnd) {
100+
return this.last() && this.prev()
101+
}
102+
return false
103+
}
104+
105+
let s = this._stack[this._stack.length - 1]
106+
if (s.node.isLeaf()) {
107+
s.index--
108+
if (s.index === -1) {
109+
for (;;) {
110+
this._stack.length--
111+
if (this._stack.length === 0) {
112+
this._atStart = true
113+
return false
114+
}
115+
s = this._stack[this._stack.length - 1]
116+
s.index--
117+
if (s.index > -1) {
118+
break
119+
}
120+
}
121+
}
122+
} else {
123+
let node = s.node.children()[s.index] as N
124+
for (;;) {
125+
this._stack.push({ node, index: node.items().length })
126+
if (node.isLeaf()) {
127+
this._stack[this._stack.length - 1].index--
128+
break
129+
}
130+
node = node.children()[node.items().length] as N
131+
}
132+
}
133+
134+
s = this._stack[this._stack.length - 1]
135+
this._item = s.node.items()[s.index]
136+
return true
137+
}
138+
139+
next(): boolean {
140+
if (!this._tree) return false
141+
if (!this._seeked) return this.first()
142+
if (this._stack.length === 0) {
143+
if (this._atStart) {
144+
return this.first() && this.next()
145+
}
146+
return false
147+
}
148+
149+
let s = this._stack[this._stack.length - 1]
150+
s.index++
151+
if (s.node.isLeaf()) {
152+
if (s.index === s.node.items().length) {
153+
for (;;) {
154+
this._stack.length--
155+
if (this._stack.length === 0) {
156+
this._atEnd = true
157+
return false
158+
}
159+
s = this._stack[this._stack.length - 1]
160+
if (s.index < s.node.items().length) {
161+
break
162+
}
163+
}
164+
}
165+
} else {
166+
let node = s.node.children()[s.index] as N
167+
for (;;) {
168+
this._stack.push({ node, index: 0 })
169+
if (node.isLeaf()) {
170+
break
171+
}
172+
node = node.children()[0] as N
173+
}
174+
}
175+
176+
s = this._stack[this._stack.length - 1]
177+
this._item = s.node.items()[s.index]
178+
return true
179+
}
180+
181+
item(): T | undefined {
182+
return this._item
183+
}
184+
185+
release(): void {
186+
if (!this._tree) return
187+
this._stack.length = 0
188+
this._tree = undefined
189+
this._item = undefined
190+
}
191+
}
192+
193+
export type { IBTree, IBTreeNode }
194+
export { BTreeIterator }
195+
196+
if (typeof require !== 'undefined' && typeof module !== 'undefined' && require.main === module) {
197+
class Node implements IBTreeNode<number> {
198+
private readonly _items: number[]
199+
private readonly _children: Node[]
200+
201+
constructor(items: number[], children: Node[]) {
202+
this._items = items
203+
this._children = children
204+
}
205+
206+
isLeaf(): boolean {
207+
return this._children.length === 0
208+
}
209+
210+
items(): number[] {
211+
return this._items
212+
}
213+
214+
children(): Node[] {
215+
return this._children
216+
}
217+
}
218+
219+
class Tree implements IBTree<Node, number> {
220+
private readonly _root: Node | undefined
221+
222+
constructor(root: Node | undefined) {
223+
this._root = root
224+
}
225+
226+
root(): Node | undefined {
227+
return this._root
228+
}
229+
230+
find(node: Node, item: number): { index: number; found: boolean } {
231+
const items = node.items()
232+
let low = 0
233+
let high = items.length - 1
234+
while (low <= high) {
235+
const mid = low + ((high - low) >>> 1)
236+
if (items[mid] === item) return { index: mid, found: true }
237+
if (items[mid] < item) {
238+
low = mid + 1
239+
} else {
240+
high = mid - 1
241+
}
242+
}
243+
return { index: low, found: false }
244+
}
245+
}
246+
247+
const root = new Node(
248+
[1, 3, 5, 7, 9],
249+
[
250+
new Node([0, 1], []),
251+
new Node([2, 3], []),
252+
new Node([4, 5], []),
253+
new Node([6, 7], []),
254+
new Node([8, 9], []),
255+
new Node([10, 11], [])
256+
]
257+
)
258+
259+
const tree = new Tree(root)
260+
const iter = new BTreeIterator(tree)
261+
262+
// output items >= 4
263+
iter.seek(4)
264+
do {
265+
console.log(iter.item())
266+
} while (iter.next())
267+
}

0 commit comments

Comments
 (0)