-
Notifications
You must be signed in to change notification settings - Fork 53
/
Copy path0222. Count Complete Tree Nodes.js
90 lines (82 loc) · 2.08 KB
/
0222. Count Complete Tree Nodes.js
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
// Given a complete binary tree, count the number of nodes.
//
// Note:
//
// Definition of a complete binary tree from Wikipedia: https://en.wikipedia.org/wiki/Binary_tree#Types_of_binary_trees
// In a complete binary tree every level, except possibly the last, is completely filled, and all nodes in the last level are as far left as possible. It can have between 1 and 2h nodes inclusive at the last level h.
//
// Example:
//
// Input:
// 1
// / \
// 2 3
// / \ /
// 4 5 6
//
// Output: 6
/**
* Definition for a binary tree node.
* function TreeNode(val) {
* this.val = val;
* this.left = this.right = null;
* }
*/
/**
* @param {TreeNode} root
* @return {number}
*/
// 1) DFS
// Time O(n)
// Space O(d) = O(log n) to keep the recursion stack, where d is a tree depth
const countNodes1 = (root) => {
if (root == null) return 0;
return countNodes(root.left) + countNodes(root.right) + 1;
};
// 2) Binary Search
// Time O(d^2) = O((log n)^2), where d is a tree depth
// Space O(1)
const countNodes = (root) => {
// if the tree is empty
if (root == null) return 0;
const d = getDepth(root);
// Last level nodes are enumerated from 0 to 2^d - 1 (left -> right).
// Perform binary search to check how many nodes exist.
let l = 0;
let r = 2 ** d - 1;
while (l <= r) {
const m = ~~((l + r) / 2);
if (exists(m, d, root)) l = m + 1;
else r = m - 1;
}
// The tree contains 2^d - 1 nodes on the first (d - 1) levels
// and l nodes on the last level.
return 2 ** d - 1 + l;
};
// Return tree depth in O(d) time.
const getDepth = (node) => {
let d = 0;
while (node.left != null) {
node = node.left;
d++;
}
return d;
};
// Last level nodes are enumerated from 0 to 2^d - 1 (left -> right).
// Return true if last level node idx exists.
// Binary search with O(d) complexity.
const exists = (idx, d, node) => {
let l = 0;
let r = 2 ** d - 1;
while (l < r) {
const m = ~~((l + r) / 2);
if (idx > m) {
node = node.right;
l = m + 1;
} else {
node = node.left;
r = m;
}
}
return node != null;
};