Get Maximum width of Binary Tree

Given a Binary tree, the task is to Get Maximum width of Binary Tree, The width of a binary tree refers to the number of nodes at a specific level of the tree.

Code Flow for Get Maximum width of Binary Tree

  • Base case: If the root node is null, meaning the width of an empty tree is 0, returns 0,

  • maxWidth: A variable to track the maximum width observed during traversal initialized to 0.

  • height: The height of the tree is determined by calling getTreeHeight.

  • Level-wise iteration:

    • The method loops through all levels from 1 to the tree's height.

    • For each level, it calls getWidth to get the number of nodes at the current level

    • If currentWidth is greater than maxWidth, the value of maxWidth is updated.

    • The method returns the largest width found during the iteration.

 

Method: getWidth

  • Base case: If the node is null, the method returns 0 since no node is present at this level.

  • If the level is 1, it means the current node is at the desired level, so the method returns 1
    • If the level is greater than 1, the method recursively calls itself on the left and right subtrees and adds the results together.


Let's see the code now

package org.wesome.dsalgo;

import lombok.Data;

import java.util.Objects;

public class BinarySearchTree {
    Node root;

    public static int getTreeHeight(Node node) {
        if (Objects.isNull(node)) {
            System.out.println("BinaryTree.countTreeHeight node is null");
            return 0;
        }
        return Math.max(getTreeHeight(node.left), getTreeHeight(node.right)) + 1;
    }

    /*  This method calculates the maximum width of the binary tree, which is the largest number of nodes present at any level in the tree. */
    public static int getMaximumWidth(Node node) {
        /*  If the root node is null, it prints a message and returns 0, meaning the width of an empty tree is 0.   */
        if (Objects.isNull(node)) {
            System.out.println("BinarySearchTree.getMaximumWidth node is null");
            return 0;
        }
        /*  variable to track the maximum width observed during traversal   */
        int maxWidth = 0;
        int currentLevelWidth;
        int treeHeight = getTreeHeight(node);

        for (int i = 1; i <= treeHeight; i++) {
            currentLevelWidth = getWidth(node, i);
            if (currentLevelWidth > maxWidth) {
                System.out.println("BinarySearchTree.getMaximumWidth treeHeight: " + treeHeight + " currentLevelWidth: " + currentLevelWidth + " maxWidth: " + maxWidth);
                maxWidth = currentLevelWidth;
            }
        }
        return maxWidth;
    }

    /*  This method calculates the number of nodes at a given level in the tree.    */
    private static int getWidth(Node node, int level) {
        /*  If the node is null, the method returns 0 since no node is present at this level.   */
        if (Objects.isNull(node)) {
            return 0;
        }
        /*  f the level is 1, it means the current node is at the desired level, so the method returns 1    */
        if (level == 1) {
            System.out.println("BinarySearchTree.getWidth level node is " + level);
            return 1;
        }

        /*  If the level is greater than 1, the method recursively calls itself on the left and right subtrees and adds the results together.  */
        else if (level > 1) {
            System.out.println("BinarySearchTree.getWidth level is greater then 1 " + level);
            return getWidth(node.left, level - 1) + getWidth(node.right, level - 1);
        }
        return 0;
    }

    void insert(int data) {
        System.out.println("BinarySearchTree.insert data = " + data);
        root = insert(root, data);
    }

    Node insert(Node root, int data) {
        if (Objects.isNull(root)) {
            Node tempNode = new Node(data);
            return tempNode;
        }
        if (data > root.data) {
            root.right = insert(root.right, data);
        } else {
            root.left = insert(root.left, data);
        }
        return root;
    }
}

@Data
class Node {
    int data;
    Node left, right;

    public Node(int data) {
        this.data = data;
        left = right = null;
    }
}
package org.wesome.dsalgo;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;

public class BinaryTreeTest {

    @Test
    void testEmptyTree() {
        BinarySearchTree tree = new BinarySearchTree();
        // Test for an empty tree (null root)
        assertEquals(0, tree.getMaximumWidth(null), "Maximum width of an empty tree should be 0");
    }

    @Test
    void testSingleNodeTree() {
        // Test for a tree with a single node
        BinarySearchTree tree = new BinarySearchTree();
        tree.insert(10);
        assertEquals(1, tree.getMaximumWidth(tree.root), "Maximum width of a single node tree should be 1");
    }

    @Test
    void testBalancedBinarySearchTree() {
        // Test for a balanced binary tree
        BinarySearchTree tree = new BinarySearchTree();
        tree.insert(10);
        tree.insert(5);
        tree.insert(15);
        tree.insert(2);
        tree.insert(7);
        tree.insert(12);
        tree.insert(18);
        assertEquals(4, tree.getMaximumWidth(tree.root), "Maximum width of balanced binary tree nodes should be correct");
    }

    @Test
    void testUnbalancedBinarySearchTree() {
        // Test for an unbalanced binary tree (sorted order insertion creating a right-skewed tree)
        BinarySearchTree tree = new BinarySearchTree();
        tree.insert(10);
        tree.insert(20);
        tree.insert(30);
        tree.insert(40);
        tree.insert(50);
        assertEquals(1, tree.getMaximumWidth(tree.root), "Maximum width of right-skewed tree nodes should be correct");
    }

    @Test
    void testTreeWithNegativeValues() {
        // Test for a tree with negative values
        BinarySearchTree tree = new BinarySearchTree();
        tree.insert(-5);
        tree.insert(-3);
        tree.insert(-2);
        tree.insert(-1);
        tree.insert(-7);
        tree.insert(-4);
        assertEquals(2, tree.getMaximumWidth(tree.root), "Maximum width of tree with negative values should be correct");
    }

    @Test
    void testLargeTree() {
        // Test for a large tree with many nodes
        BinarySearchTree tree = new BinarySearchTree();
        for (int i = 1; i <= 1000; i++) {
            tree.insert(i);
        }
        assertEquals(1, tree.getMaximumWidth(tree.root), "Maximum width of large tree should be correct");
    }

    @Test
    void testBalancedTree() {
        Node root = new Node(10);
        root.left = new Node(5);
        root.right = new Node(15);
        root.left.left = new Node(2);
        root.left.right = new Node(7);
        root.right.left = new Node(12);
        root.right.right = new Node(18);
        assertEquals(4, BinarySearchTree.getMaximumWidth(root), "Maximum width of Balanced Tree should be correct");
    }

    @Test
    void testRightSkewedTree() {
        // Constructing the following tree:
        //          10
        //           \
        //            20
        //             \
        //              30
        //               \
        //                40
        //                 \
        //                  50
        Node root = new Node(10);
        root.right = new Node(20);
        root.right.right = new Node(30);
        root.right.right.right = new Node(40);
        root.right.right.right.right = new Node(50);
        assertEquals(1, BinarySearchTree.getMaximumWidth(root), "Maximum width of Right Skewed should be correct");
    }

    @Test
    void testLeftSkewedTree() {
        // Constructing the following tree:
        //              10
        //             /
        //           20
        //          /
        //        30
        //       /
        //     40
        //    /
        //  50
        Node root = new Node(10);
        root.left = new Node(20);
        root.left.left = new Node(30);
        root.left.left.left = new Node(40);
        root.left.left.left.left = new Node(50);
        assertEquals(1, BinarySearchTree.getMaximumWidth(root), "Maximum width of Left Skewed should be correct");
    }

    @Test
    void testTreeWithDuplicateValues() {
        // Constructing the following tree:
        //          1
        //       /    \
        //      1       1
        //     / \     / \
        //    1   1   1   1
        Node root = new Node(1);
        root.left = new Node(1);
        root.right = new Node(1);
        root.left.left = new Node(1);
        root.left.right = new Node(1);
        root.right.left = new Node(1);
        root.right.right = new Node(1);
        assertEquals(4, BinarySearchTree.getMaximumWidth(root), "Maximum width of Tree with duplicate values.");
    }

    @Test
    public void testCompleteBinaryTree() {
        Node root = new Node(10);
        root.left = new Node(5);
        root.right = new Node(15);
        root.left.left = new Node(3);
        root.left.right = new Node(7);
        root.right.left = new Node(12);
        root.right.right = new Node(18);
        root.left.left.left = new Node(1);
        root.left.left.right = new Node(4);
        assertEquals(4, BinarySearchTree.getMaximumWidth(root), "Height of a complete binary tree should be 4.");
    }
}
plugins {
    id("java")
    id("io.freefair.lombok") version "8.13"
}

group = "org.wesome.dsalgo"
version = "1.0-SNAPSHOT"

repositories {
    mavenCentral()
}

dependencies {
    testImplementation(platform("org.junit:junit-bom:5.10.0"))
    testImplementation("org.junit.jupiter:junit-jupiter")
}

tasks.test {
    useJUnitPlatform()
}

Complexity Analysis

  • Time Complexity: O(n²) in the worst case for skewed trees

  • Space Complexity: O(n) due to recursion stack

follow us on