-
Notifications
You must be signed in to change notification settings - Fork 30
/
count_nodes_for_complete_tree.rb
61 lines (56 loc) · 1.14 KB
/
count_nodes_for_complete_tree.rb
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
MEMO = {}
def count_nodes(root)
return 0 unless root
left_height, left_full = height_and_full?(root.left)
left_full ? 2 ** left_height + count_nodes(root.right)
: 2 ** (left_height - 1) + count_nodes(root.left)
end
def height_and_full?(root)
return MEMO[root] if MEMO[root]
return [0, true] unless root
p, q = root.left, root.right
height = 1
while p && q
p, q = p.left, q.right
height += 1
end
MEMO[root] = p && !q ? [height + 1, false] : [height, true]
end
# Q-222: binary search way for counting complete tree nodes
# 10/dec/2022
def count_nodes(root)
return 0 unless root
return 1 unless root.left || root.right
h = height(root)
delta = 2 ** (h - 2)
left, right = 0, delta * 2
while left < right
m = (left + right) / 2
if bsearch(root, m, delta)
left = m + 1
else
right = m
end
end
2 ** (h - 1) + left - 1
end
def height(root)
h = 0
while root
h += 1
root = root.left
end
h
end
def bsearch(root, i, delta)
while root && delta > 0
if i < delta
root = root.left
else
root = root.right
i -= delta
end
delta /= 2
end
root != nil
end