forked from NKaty/Algorithms-and-Data-Structures
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpseudo-palindromic-paths-in-a-binary-tree.js
More file actions
75 lines (66 loc) · 2.64 KB
/
pseudo-palindromic-paths-in-a-binary-tree.js
File metadata and controls
75 lines (66 loc) · 2.64 KB
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
// Given a binary tree where node values are digits from 1 to 9.
// A path in the binary tree is said to be pseudo-palindromic
// if at least one permutation of the node values in the path is a palindrome.
// Return the number of pseudo-palindromic paths going from the root node to leaf nodes.
// Constraints:
// The number of nodes in the tree is in the range [1, 10 ^ 5]
// 1 <= Node.val <= 9
function TreeNode(val, left, right) {
this.val = (val === undefined ? 0 : val);
this.left = (left === undefined ? null : left);
this.right = (right === undefined ? null : right);
}
const getTree = (arr) => {
if (!arr.length) throw new Error('Array is empty.');
const build = (node, index) => {
if (arr[index * 2 + 1] !== null && arr[index * 2 + 1] !== undefined) {
node.left = new TreeNode(arr[index * 2 + 1]);
build(node.left, index * 2 + 1);
}
if (arr[index * 2 + 2] !== null && arr[index * 2 + 2] !== undefined) {
node.right = new TreeNode(arr[index * 2 + 2]);
build(node.right, index * 2 + 2);
}
};
const root = new TreeNode(arr[0]);
build(root, 0);
return root;
};
const pseudoPalindromicPaths = (root) => {
if (!root) return 0;
let count = 0;
// The idea is to use path as a bitmask to track
// how many digits in this branch have an odd frequency
// If there are more than one such digits, then the path
// is not pseudo-palindromic
// For example, [2, 3, 1, 3, 1, null, 1]
// 2
// / \
// 3 1
// / \ \
// 3 1 1
// Possible paths:
// 2 -> 3 -> 3 --> 0100 -> 1100 -> 0100 --> pseudo-palindromic
// 2 -> 3 -> 1 --> 0100 -> 1100 -> 1110 --> not pseudo-palindromic
// 2 -> 1 -> 1 --> 0100 -> 0110 -> 0100 --> pseudo-palindromic
const dfs = (node, path = 0) => {
// We can use a 32-bit integer as a bitmask,
// because according to the constrains the values
// of nodes can be from 1 to 9
// The one means digit has an odd frequency
// The zero means digit has an even frequency
path ^= (1 << node.val);
// If the node doesn't have children, we can check the path
// If we don't have any odd digits or have only one
// the expresion: path & (path - 1) will be 0
// as it flips the least-significant bit to 0
if (!node.left && !node.right) count += !(path & (path - 1));
// Otherwise, we keep constructing the path
if (node.left) dfs(node.left, path);
if (node.right) dfs(node.right, path);
};
dfs(root);
return count;
};
console.log(pseudoPalindromicPaths(getTree([2, 3, 1, 3, 1, null, 1]))); // 2
console.log(pseudoPalindromicPaths(getTree([2, 1, 1, 1, 3, null, null, null, null, null, 1]))); // 1