diff --git a/Trees/DiameterOfBinaryTree.js b/Trees/DiameterOfBinaryTree.js new file mode 100644 index 0000000000..d9083a7551 --- /dev/null +++ b/Trees/DiameterOfBinaryTree.js @@ -0,0 +1,27 @@ +/** + * Calculates the diameter of a binary tree. + * The diameter is the length of the longest path between any two nodes. + * This path does not necessarily need to pass through the root. + * @param {TreeNode} root The root node of the tree. + * @returns {number} The diameter of the tree. + * @see {@link https://en.wikipedia.org/wiki/Tree_(graph_theory)#Properties} + */ +export function diameterOfBinaryTree(root) { + let diameter = 0; + + function height(node) { + if (node === null) { + return 0; + } + + const leftHeight = height(node.left); + const rightHeight = height(node.right); + + diameter = Math.max(diameter, leftHeight + rightHeight); + + return 1 + Math.max(leftHeight, rightHeight); + } + + height(root); + return diameter; +} diff --git a/Trees/test/DiameterOfBinaryTree.test.js b/Trees/test/DiameterOfBinaryTree.test.js new file mode 100644 index 0000000000..4bdf43cf39 --- /dev/null +++ b/Trees/test/DiameterOfBinaryTree.test.js @@ -0,0 +1,58 @@ +/** + * A node for a binary tree. + */ +class TreeNode { + constructor(value) { + this.value = value; + this.left = null; + this.right = null; + } +} + +import { diameterOfBinaryTree } from './DiameterOfBinaryTree'; + + +describe('Diameter of a Binary Tree', () => { + it('should calculate the correct diameter for a standard tree', () => { + // 1 + // / \ + // 2 3 + // / \ + // 4 5 + // Longest path is 4 -> 2 -> 1 -> 3 (length 3) or 5 -> 2 -> 1 -> 3 (length 3) + const root = new TreeNode(1); + root.left = new TreeNode(2); + root.right = new TreeNode(3); + root.left.left = new TreeNode(4); + root.left.right = new TreeNode(5); + expect(diameterOfBinaryTree(root)).toBe(3); + }); + + it('should work for a skewed tree where diameter does not pass through root', () => { + // 1 + // / + // 2 + // / \ + // 3 4 + // / \ + // 5 6 + // / \ + // 7 8 + // Longest path is 7 -> 5 -> 4 -> 6 -> 8 (length 4) + const root = new TreeNode(1); + root.left = new TreeNode(2); + root.left.left = new TreeNode(3); + root.left.right = new TreeNode(4); + root.left.right.left = new TreeNode(5); + root.left.right.right = new TreeNode(6); + root.left.right.left.left = new TreeNode(7); + root.left.right.right.right = new TreeNode(8); + expect(diameterOfBinaryTree(root)).toBe(6); + }); + + it('should return 0 for a null or single-node tree', () => { + expect(diameterOfBinaryTree(null)).toBe(0); + const singleNode = new TreeNode(1); + expect(diameterOfBinaryTree(singleNode)).toBe(0); + }); +});