Skip to content

Commit d20397e

Browse files
author
Dinghao LI
committed
064
1 parent fc13aab commit d20397e

File tree

7 files changed

+313
-0
lines changed

7 files changed

+313
-0
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# 题意
2+
3+
4+
```
5+
5
6+
/ \
7+
3 7
8+
/ \ /\
9+
2 4 6 8
10+
```
11+
12+
给定一棵二叉搜索树,请找出其中的第k小的结点。例如, (5,3,7,2,4,6,8) 中,按结点数值大小顺序第三小结点的值为4。
13+
14+
二叉搜索树的中序遍历正好是一个递增的序列,因此中序遍历的第K个结点就是二叉搜索树的第K个节点
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
)
6+
7+
type TreeNode struct {
8+
Val int
9+
Left *TreeNode
10+
Right *TreeNode
11+
}
12+
13+
func getKth(root *TreeNode, k int) *TreeNode {
14+
if root == nil || k<1 {
15+
return nil
16+
}
17+
var res *TreeNode
18+
found := false
19+
var inOrder func(*TreeNode)
20+
inOrder = func(node *TreeNode) {
21+
if found == true || node == nil {
22+
return
23+
}
24+
inOrder(node.Left)
25+
if k == 1 {
26+
res = node
27+
found = true
28+
}
29+
k--
30+
inOrder(node.Right)
31+
}
32+
inOrder(root)
33+
return res
34+
}
35+
36+
37+
func print(root *TreeNode) {
38+
if root == nil {
39+
return
40+
}
41+
print(root.Left)
42+
fmt.Printf("%d -> ", root.Val)
43+
print(root.Right)
44+
}
45+
46+
func main() {
47+
// q1 5
48+
// q2 3 7
49+
// q1 1 4 6 8
50+
root := &TreeNode{5, &TreeNode{3, &TreeNode{1, nil, nil}, &TreeNode{4, nil, nil}}, &TreeNode{7, &TreeNode{6, nil, nil}, &TreeNode{8, nil, nil}}}
51+
print(root)
52+
fmt.Println("")
53+
fmt.Println("Get 1th: ", getKth(root, 1).Val)
54+
fmt.Println("Get 2th: ", getKth(root, 2).Val)
55+
fmt.Println("Get 3th: ", getKth(root, 3).Val)
56+
fmt.Println("Get 4th: ", getKth(root, 4).Val)
57+
fmt.Println("Get 5th: ", getKth(root, 5).Val)
58+
fmt.Println("Get 6th: ", getKth(root, 6).Val)
59+
fmt.Println("Get 7th: ", getKth(root, 7).Val)
60+
fmt.Println("Get 8th: ", getKth(root, 8))
61+
62+
63+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# 题意
2+
3+
题目描述
4+
5+
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
6+
7+
# 堆排序策略
8+
9+
对于数据流,对应的就是在线算法了,一道很经典的题目就是在1亿个数中找到最大的前100个数,这是一道堆应用题,找最大的前100个数,那么我们就创建一个大小为100的最小化堆,每来一个元素就与堆顶元素比较,因为堆顶元素是目前前100大数中的最小数,前来的元素如果比该元素大,那么就把原来的堆顶替换掉。
10+
11+
那么对于这一道题呢?如果单纯的把所有元素放到一个数组里,每次查找中位数最快也要O(n),综合下来是O(n^2)的复杂度。我们可以利用上面例子中的想法,用一个最大堆来维护当前前n/2小的元素,那么每次找中位数只到取出堆顶就可以了。但是,有一个问题,数据要动态增长,有可能之前被替换掉的元素随着元素的增加又跑回来了,所以我们不能单纯得向上题一样把元素丢掉,我们可以再用一个最小化堆来存前n/2大的元素。
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package main
2+
3+
import (
4+
"../utils"
5+
"fmt"
6+
)
7+
8+
type Solution struct {
9+
max *utils.MaxHeap
10+
min *utils.MinHeap
11+
}
12+
13+
func (s *Solution) Insert(num int) {
14+
if ((s.max.Length() + s.min.Length()) & 1) == 0 {
15+
// 偶数数据的情况下
16+
// 直接将新的数据插入到数组的后半段
17+
// 即在最小堆中插入元素
18+
// 此时最小堆中多出一个元素,
19+
// 即最小元素, 将其弹出后, 压入前半段(即最大堆中)
20+
if s.max.Length() > 0 && num < s.max.GetMax() {
21+
s.max.Insert(num)
22+
val, _ := s.max.DeleteMax()
23+
s.min.Insert(val)
24+
} else {
25+
s.min.Insert(num)
26+
}
27+
} else {
28+
// 奇数情况
29+
if s.max.Length() > 0 && num < s.max.GetMax() {
30+
s.max.Insert(num)
31+
} else {
32+
s.min.Insert(num)
33+
val, _ := s.min.DeleteMin()
34+
s.max.Insert(val)
35+
}
36+
}
37+
}
38+
39+
func (s *Solution) GetMedian() float64 {
40+
size := s.max.Length() + s.min.Length()
41+
if size == 0 {
42+
return -1
43+
}
44+
var median float64
45+
if size&1 != 0 {
46+
median = float64(s.min.GetMin())
47+
} else {
48+
median = float64(s.min.GetMin() + s.max.GetMax()) / 2
49+
}
50+
return median
51+
}
52+
53+
54+
func main() {
55+
56+
sol := &Solution{utils.NewMaxHeap(), utils.NewMinHeap()}
57+
sol.Insert(1)
58+
fmt.Println("Insert 1")
59+
fmt.Println(sol.GetMedian())
60+
61+
sol.Insert(2)
62+
fmt.Println("Insert 2")
63+
fmt.Println(sol.GetMedian())
64+
65+
sol.Insert(3)
66+
fmt.Println("Insert 3")
67+
fmt.Println(sol.GetMedian())
68+
69+
sol.Insert(4)
70+
fmt.Println("Insert 4")
71+
fmt.Println(sol.GetMedian())
72+
73+
sol.Insert(5)
74+
fmt.Println("Insert 5")
75+
fmt.Println(sol.GetMedian())
76+
77+
}

utils/maxHeap.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@ func (H *MaxHeap) Max() (int, error) {
3131
return -1, fmt.Errorf("heap is empty")
3232
}
3333

34+
// Get the Maximum of the Maxheap
35+
func (H *MaxHeap) GetMax() int {
36+
if H.Length() > 0 {
37+
return H.Element[1]
38+
}
39+
return math.MaxInt64
40+
}
41+
3442
// Inserting items requires ensuring the nature of the Maxheap
3543
func (H *MaxHeap) Insert(v int) {
3644
H.Element = append(H.Element, v)

utils/minHeap.go

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package utils
2+
3+
import (
4+
"fmt"
5+
"math"
6+
)
7+
8+
type MinHeap struct {
9+
Element []int
10+
}
11+
12+
13+
14+
// MinHeap constructor
15+
func NewMinHeap() *MinHeap {
16+
first := math.MinInt64
17+
h := &MinHeap{Element: []int{first}}
18+
return h
19+
}
20+
21+
// Length of Minheap
22+
func (H *MinHeap) Length() int {
23+
return len(H.Element) - 1
24+
}
25+
26+
// Get the Minimum of the Minheap
27+
func (H *MinHeap) Min() (int, error) {
28+
if len(H.Element) > 1 {
29+
return H.Element[1], nil
30+
}
31+
return -1, fmt.Errorf("heap is empty")
32+
}
33+
34+
// Get the Minimum of the Minheap
35+
func (H *MinHeap) GetMin() int {
36+
if H.Length() > 0 {
37+
return H.Element[1]
38+
}
39+
return math.MinInt64
40+
}
41+
42+
// Inserting items requires ensuring the nature of the Minheap
43+
func (H *MinHeap) Insert(v int) {
44+
H.Element = append(H.Element, v)
45+
i := len(H.Element) - 1
46+
for ; (H.Element[i/2]) > v; i /= 2 {
47+
H.Element[i] = H.Element[i/2]
48+
}
49+
50+
H.Element[i] = v
51+
}
52+
53+
// Delete and return the Minimum
54+
func (H *MinHeap) DeleteMin() (int, error) {
55+
if len(H.Element) <= 1 {
56+
return -1, fmt.Errorf("MinHeap is empty")
57+
}
58+
MinElement := H.Element[1]
59+
lastElement := H.Element[len(H.Element)-1]
60+
var i, child int
61+
for i = 1; i*2 < len(H.Element); i = child {
62+
child = i * 2
63+
if child < len(H.Element)-1 && H.Element[child+1] < H.Element[child] {
64+
child++
65+
}
66+
if lastElement > H.Element[child] {
67+
H.Element[i] = H.Element[child]
68+
} else {
69+
break
70+
}
71+
}
72+
H.Element[i] = lastElement
73+
H.Element = H.Element[:len(H.Element)-1]
74+
return MinElement, nil
75+
}

utils/minHeap_test.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package utils
2+
3+
import (
4+
"testing"
5+
"fmt"
6+
)
7+
8+
func Test_MinHeap(t *testing.T) {
9+
heap := NewMinHeap()
10+
if heap.Length() == 0 {
11+
t.Log("Pass")
12+
} else {
13+
t.Error("Failed")
14+
}
15+
16+
heap.Insert(1)
17+
heap.Insert(2)
18+
heap.Insert(3)
19+
heap.Insert(4)
20+
heap.Insert(5)
21+
22+
23+
if heap.Length() == 5 {
24+
t.Log("Pass")
25+
} else {
26+
t.Error("Failed")
27+
}
28+
29+
v, _ := heap.Min()
30+
if v == 1 {
31+
t.Log("Pass")
32+
} else {
33+
t.Error("Failed")
34+
}
35+
36+
v, _ = heap.DeleteMin()
37+
if v == 1 {
38+
t.Log("Pass")
39+
} else {
40+
t.Error("Failed")
41+
}
42+
43+
v, _ = heap.DeleteMin()
44+
if v == 2 {
45+
t.Log("Pass")
46+
} else {
47+
fmt.Println(v)
48+
t.Error("Failed")
49+
}
50+
v, _ = heap.DeleteMin()
51+
if v == 3 {
52+
t.Log("Pass")
53+
} else {
54+
fmt.Println(v)
55+
t.Error("Failed")
56+
}
57+
v, _ = heap.DeleteMin()
58+
if v == 4 {
59+
t.Log("Pass")
60+
} else {
61+
fmt.Println(v)
62+
t.Error("Failed")
63+
}
64+
65+
}

0 commit comments

Comments
 (0)