Skip to content

Commit c118a15

Browse files
committed
feat(solutions): add recover_binary_search_tree
1 parent a18df38 commit c118a15

File tree

5 files changed

+222
-0
lines changed

5 files changed

+222
-0
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ If you like it then you can put a :star:**Star** on it.
3434
3535
| # | **Problem** & **Solution** | Difficulty | Single Repetition Duration | LeetCode Run Time |
3636
| ---: | :----- | :----------: | ----------: | ----------: |
37+
|[99][Solutions-99]|[Recover Binary Search Tree][Solutions-99-Home]|Hard|[94.8 ns/op][Solutions-99-Code] / [3 test cases][Solutions-99-Test]|32 ms|
3738
|[98][Solutions-98]|[Validate Binary Search Tree][Solutions-98-Home]|Medium|[21.0 ns/op][Solutions-98-Code] / [8 test cases][Solutions-98-Test]|8 ms|
3839
|[96][Solutions-96]|[Unique Binary Search Trees][Solutions-96-Home]|Medium|[39.1 ns/op][Solutions-96-Code] / [6 test cases][Solutions-96-Test]|0 ms|
3940
|[95][Solutions-95]|[Unique Binary Search Trees II][Solutions-95-Home]|Medium|[259 ns/op][Solutions-95-Code] / [3 test cases][Solutions-95-Test]|48 ms|
@@ -154,6 +155,10 @@ Welcome to report bugs, suggest ideas and discuss on [issues page](https://githu
154155
## License
155156
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2FWindomZ%2Fleetcode.go.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2FWindomZ%2Fleetcode.go?ref=badge_large)
156157

158+
[Solutions-99]:https://leetcode.com/problems/recover-binary-search-tree/
159+
[Solutions-99-Home]:solutions/recover_binary_search_tree/
160+
[Solutions-99-Code]:solutions/recover_binary_search_tree/recoverbinarysearchtree.go
161+
[Solutions-99-Test]:solutions/recover_binary_search_tree/recoverbinarysearchtree_test.go#L113
157162
[Solutions-98]:https://leetcode.com/problems/validate-binary-search-tree/
158163
[Solutions-98-Home]:solutions/validate_binary_search_tree/
159164
[Solutions-98-Code]:solutions/validate_binary_search_tree/validatebinarysearchtree.go
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# 解法要点
2+
1. BST(binary search trees)是左叶值小于节点值,右叶值大于节点值
3+
1. 运用Morris Traversal方法遍历二叉树,找出两个错误的数值
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# [99. Recover Binary Search Tree](https://leetcode.com/problems/recover-binary-search-tree/description/)
2+
3+
## Description
4+
5+
Two elements of a binary search tree (BST) are swapped by mistake.
6+
7+
Recover the tree without changing its structure.
8+
9+
**Note:**
10+
11+
A solution using O(_n_) space is pretty straight forward. Could you devise a constant space solution?
12+
13+
## Solution
14+
- [Code](recoverbinarysearchtree.go)
15+
- [Testing](recoverbinarysearchtree_test.go)
16+
17+
## Note
18+
- [中文](NOTE_Ch-zh.md)
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package recoverbinarysearchtree
2+
3+
// TreeNode definition for a binary tree node.
4+
type TreeNode struct {
5+
Val int
6+
Left *TreeNode
7+
Right *TreeNode
8+
}
9+
10+
func recoverTree(root *TreeNode) {
11+
var pre, cur, first, second *TreeNode
12+
// Morris Traversal
13+
// https://en.wikipedia.org/wiki/Threaded_binary_tree#The_array_of_Inorder_traversal
14+
for root != nil {
15+
if root.Left != nil {
16+
// connect threading for root
17+
cur = root.Left
18+
for cur.Right != nil && cur.Right != root {
19+
cur = cur.Right
20+
}
21+
// the threading already exists
22+
if cur.Right != nil {
23+
if pre != nil && pre.Val > root.Val {
24+
// found the mistaken nodes
25+
if first == nil {
26+
first = pre
27+
}
28+
second = root
29+
}
30+
pre, cur.Right, root = root, nil, root.Right
31+
} else {
32+
// construct the threading
33+
cur.Right, root = root, root.Left
34+
}
35+
} else {
36+
if pre != nil && pre.Val > root.Val {
37+
// found the mistaken nodes
38+
if first == nil {
39+
first = pre
40+
}
41+
second = root
42+
}
43+
pre, root = root, root.Right
44+
}
45+
}
46+
// swap the two mistaken nodes
47+
if first != nil && second != nil {
48+
first.Val, second.Val = second.Val, first.Val
49+
}
50+
}
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
package recoverbinarysearchtree
2+
3+
import (
4+
"testing"
5+
6+
"github.com/WindomZ/testify/assert"
7+
)
8+
9+
func Test_recoverTree(t *testing.T) {
10+
root := &TreeNode{
11+
Val: 3,
12+
Left: &TreeNode{
13+
Val: 1,
14+
Left: &TreeNode{Val: 2},
15+
},
16+
}
17+
recoverTree(root)
18+
assert.Equal(t, &TreeNode{
19+
Val: 3,
20+
Left: &TreeNode{
21+
Val: 2,
22+
Left: &TreeNode{Val: 1},
23+
},
24+
}, root)
25+
26+
root = &TreeNode{
27+
Val: 2,
28+
Left: &TreeNode{
29+
Val: 3,
30+
},
31+
Right: &TreeNode{
32+
Val: 1,
33+
},
34+
}
35+
recoverTree(root)
36+
assert.Equal(t, &TreeNode{
37+
Val: 2,
38+
Left: &TreeNode{
39+
Val: 1,
40+
},
41+
Right: &TreeNode{
42+
Val: 3,
43+
},
44+
}, root)
45+
46+
root = &TreeNode{
47+
Val: 3,
48+
Right: &TreeNode{
49+
Val: 2,
50+
Right: &TreeNode{
51+
Val: 1,
52+
},
53+
},
54+
}
55+
recoverTree(root)
56+
assert.Equal(t, &TreeNode{
57+
Val: 1,
58+
Right: &TreeNode{
59+
Val: 2,
60+
Right: &TreeNode{
61+
Val: 3,
62+
},
63+
},
64+
}, root)
65+
66+
root = &TreeNode{
67+
Val: 4,
68+
Left: &TreeNode{
69+
Val: 2,
70+
Left: &TreeNode{Val: 3},
71+
},
72+
Right: &TreeNode{Val: 5},
73+
}
74+
recoverTree(root)
75+
assert.Equal(t, &TreeNode{
76+
Val: 4,
77+
Left: &TreeNode{
78+
Val: 3,
79+
Left: &TreeNode{Val: 2},
80+
},
81+
Right: &TreeNode{Val: 5},
82+
}, root)
83+
84+
root = &TreeNode{
85+
Val: 4,
86+
Left: &TreeNode{
87+
Val: 2,
88+
Right: &TreeNode{
89+
Val: 3,
90+
}},
91+
Right: &TreeNode{
92+
Val: 6,
93+
Left: &TreeNode{
94+
Val: 7,
95+
}},
96+
}
97+
recoverTree(root)
98+
assert.Equal(t, &TreeNode{
99+
Val: 4,
100+
Left: &TreeNode{
101+
Val: 2,
102+
Right: &TreeNode{
103+
Val: 3,
104+
}},
105+
Right: &TreeNode{
106+
Val: 7,
107+
Left: &TreeNode{
108+
Val: 6,
109+
}},
110+
}, root)
111+
}
112+
113+
func Benchmark_recoverTree(b *testing.B) {
114+
b.StopTimer()
115+
b.ReportAllocs()
116+
b.StartTimer()
117+
b.RunParallel(func(pb *testing.PB) {
118+
for pb.Next() {
119+
recoverTree(&TreeNode{
120+
Val: 3,
121+
Left: &TreeNode{
122+
Val: 1,
123+
Left: &TreeNode{Val: 2},
124+
},
125+
})
126+
recoverTree(&TreeNode{
127+
Val: 1,
128+
Left: &TreeNode{Val: 2},
129+
Right: &TreeNode{Val: 3},
130+
})
131+
recoverTree(&TreeNode{
132+
Val: 3,
133+
Left: &TreeNode{
134+
Val: 2,
135+
Right: &TreeNode{
136+
Val: 4,
137+
}},
138+
Right: &TreeNode{
139+
Val: 3,
140+
Left: &TreeNode{
141+
Val: 4,
142+
}},
143+
})
144+
}
145+
})
146+
}

0 commit comments

Comments
 (0)