This repository has been archived by the owner on Jun 24, 2021. It is now read-only.
forked from hoanhan101/algo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
2nd_largest_item_bst_test.go
137 lines (115 loc) · 3.62 KB
/
2nd_largest_item_bst_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
Problem:
- Given a binary search tree, find the 2nd largest item.
Example:
- Input:
5
3 8
2 4 7 9
1 11
Output: 9
- Input:
5
3 8
2 4 7 16
11
9 12
Output: 12
Approach:
- The largest item in a binary search tree is the rightmost item. Can
simply traverse down the tree recursively to find one.
- The 2nd largest item could be the parent of the largest but it's not
necessary since the largest could have a left subtree and there might exist
one there.
- Still, the second largest one when the largest has a left subtree is basically
the largest one in that left subtree.
Cost:
- O(h) time, O(1) space, where h is the height of the tree.
- If the tree is balanced, the time complexity is (Olgn). Otherwise, it's O(n).
*/
package interviewcake
import (
"testing"
"github.com/hoanhan101/algo/common"
)
func Test2ndLargestItem(t *testing.T) {
// define test cases' input.
t1 := &BinaryTree{nil, 1, nil}
t2 := &BinaryTree{nil, 1, nil}
t2.right = &BinaryTree{nil, 2, nil}
t3 := &BinaryTree{nil, 5, nil}
t3.left = &BinaryTree{nil, 3, nil}
t3.right = &BinaryTree{nil, 8, nil}
t4 := &BinaryTree{nil, 5, nil}
t4.left = &BinaryTree{nil, 3, nil}
t4.right = &BinaryTree{nil, 8, nil}
t4.right.left = &BinaryTree{nil, 7, nil}
t4.right.right = &BinaryTree{nil, 9, nil}
t5 := &BinaryTree{nil, 5, nil}
t5.left = &BinaryTree{nil, 3, nil}
t5.left.left = &BinaryTree{nil, 2, nil}
t5.left.left.left = &BinaryTree{nil, 1, nil}
t5.left.right = &BinaryTree{nil, 4, nil}
t5.right = &BinaryTree{nil, 8, nil}
t5.right.left = &BinaryTree{nil, 7, nil}
t5.right.right = &BinaryTree{nil, 9, nil}
t5.right.right.right = &BinaryTree{nil, 11, nil}
t6 := &BinaryTree{nil, 5, nil}
t6.left = &BinaryTree{nil, 3, nil}
t6.right = &BinaryTree{nil, 8, nil}
t6.right.left = &BinaryTree{nil, 7, nil}
t6.right.right = &BinaryTree{nil, 16, nil}
t6.right.right.left = &BinaryTree{nil, 11, nil}
t6.right.right.left.left = &BinaryTree{nil, 9, nil}
t6.right.right.left.right = &BinaryTree{nil, 12, nil}
// define their outputs.
tests := []struct {
in *BinaryTree
expected int
}{
{t1, -1}, // doesn't have at least 2 nodes, return -1
{t2, 1},
{t3, 5}, // return the rightmost one
{t4, 8}, // return the rightmost one
{t5, 9}, // return the rightmost one
{t6, 12}, // not the rightmost one, but the largest one in its subtree
}
for _, tt := range tests {
result := findSecondLargest(tt.in)
common.Equal(t, tt.expected, result)
}
}
func findSecondLargest(t *BinaryTree) int {
// if the tree is nil or doesn't have at least 2 nodes, return -1.
if (t == nil) || (t.left == nil && t.right == nil) {
return -1
}
current := t
for current != nil {
// if the current node is the largest node and it has a left subtree
// then the 2nd largest one is the largest in that subtree.
if (current.left != nil) && (current.right == nil) {
return findLargest(current.left)
}
// if the current node is the parent of the largest node and the
// largest has no children, it is the 2nd largest one.
if (current.right != nil) && (current.right.right == nil) && (current.right.left == nil) {
return current.value
}
current = current.right
}
return -1
}
// findLargest finds the largest item in a binary search tree.
func findLargest(t *BinaryTree) int {
current := t
for current != nil {
// if there is no right child, we found the right most item so simply
// return its value. otherwise, step down to this child and recurse.
if current.right == nil {
return current.value
}
current = current.right
}
return -1
}