Skip to content

Problems

Binary Tree

Diameter of Binary Tree

Problem Statement: Find the diameter of a binary tree

Approach:

The diameter of a binary tree is the length of the longest path between any two nodes in the tree. This path may or may not pass through the root.

int diameter(Node root) {
    if (root == null) return 0;
    int leftHeight = height(root.left);
    int rightHeight = height(root.right);
    int leftDiameter = diameter(root.left);
    int rightDiameter = diameter(root.right);
    return Math.max(leftHeight + rightHeight + 1, Math.max(leftDiameter, rightDiameter));
}
int height(Node node) {
    if (node == null) return 0;
    return 1 + Math.max(height(node.left), height(node.right));
}

Maximum sum level

Problem Statement: Find the level in a binary tree that has maximum sum.

Approach:
Same as finding num of levels but keep track of the level sum.

int maxLevelSum(Node root) {
    if (root == null) return 0;
    Queue<Node> queue = new LinkedList<>();
    queue.add(root);
    int maxSum = Integer.MIN_VALUE;

    while (!queue.isEmpty()) {
        int levelSize = queue.size();
        int levelSum = 0;

        for (int i = 0; i < levelSize; i++) {
            Node node = queue.poll();
            levelSum += node.data;

            if (node.left != null) {
                queue.add(node.left);
            }
            if (node.right != null) {
                queue.add(node.right);
            }
        }
        maxSum = Math.max(maxSum, levelSum);
    }
    return maxSum;
}


LCA of 2 nodes

Problem Statement: Find the lowest common ancestor of two nodes in a binary tree

Approach:
The LCA of two nodes in a binary tree is the deepest node that is an ancestor of both nodes.

Node lca(Node root, int n1, int n2) {
    if (root == null) return null;
    if (root.data == n1 || root.data == n2) return root;

    Node leftLCA = lca(root.left, n1, n2);
    Node rightLCA = lca(root.right, n1, n2);

    if (leftLCA != null && rightLCA != null) {
        return root; // This is the LCA
    }
    return (leftLCA != null) ? leftLCA : rightLCA; // Return non-null child
}

Construct BT from Inorder and Preorder

Problem Statement: Given an inorder traversal and preorder traversal of a binary tree. Build the binary tree from them.

Approach:
LDR + DLR The first element in the preorder traversal is the root. Find this root in the inorder traversal to determine the left and right subtrees. Repeat this process recursively for the left and right subtrees.

Node buildTree(int[] inorder, int[] preorder, int inStart, int inEnd, int preStart, int preEnd) {
    if (inStart > inEnd || preStart > preEnd) return null;

    Node root = new Node(preorder[preStart]);
    int inIndex = findIndex(inorder, inStart, inEnd, root.data);

    root.left = buildTree(inorder, preorder, inStart, inIndex - 1, preStart + 1, preStart + (inIndex - inStart));
    root.right = buildTree(inorder, preorder, inIndex + 1, inEnd, preStart + (inIndex - inStart) + 1, preEnd);

    return root;
}


Given 2 traversal, can we construct unique BT?

To build a unique BT we need inorder and any one of the other traversals (preorder, level order or postorder).


Zigzag Level Order Traversal

Problem Statement: Print the zigzag level order traversal of a binary tree.

Approach:
Maintain 2 stacks and a boolean to track the direction of traversal.
If the boolean is true, pop from the first stack and push children to the second stack in left-to-right order.
If false, do the opposite.

void zigzagLevelOrder(Node root) {
    if (root == null) return;

    Stack<Node> currentLevel = new Stack<>();
    Stack<Node> nextLevel = new Stack<>();
    boolean leftToRight = true;

    currentLevel.push(root);

    while (!currentLevel.isEmpty()) {
        Node node = currentLevel.pop();
        System.out.print(node.data + " ");

        if (leftToRight) {
            if (node.left != null) nextLevel.push(node.left);
            if (node.right != null) nextLevel.push(node.right);
        } else {
            if (node.right != null) nextLevel.push(node.right);
            if (node.left != null) nextLevel.push(node.left);
        }

        if (currentLevel.isEmpty()) {
            leftToRight = !leftToRight;
            Stack<Node> temp = currentLevel;
            currentLevel = nextLevel;
            nextLevel = temp;
        }
    }
    System.out.println();
}


Maximum Path Sum

Problem Statement:

Approach:
At each node find max(left_max_sum, right_max_sum, left_h_sum + node + right_h_sum)

Refer Problem 124


Serialize and Deserialize BT

Problem Statement: Design an algorithm to serialize and deserialize a binary tree.

Approach:

Refer Problem 297


Binary Search Tree

Number of BSTs possible with n nodes

Refer DP Problem


Check if a BT is BST

Problem Statement: Give a binary tree, return true if its a bst else false

Approach:

  • Inorder traversal has ascending order
  • Find the max value in left subtree is less than node data and min value in right subtree is greater than node data.
fun isBST(root: TreeNode): Boolean {
//    if(root == null) return true;
//    if(!isBST(root->left, prev))
//        return false;
//    if(root.data < prev)
//        return false;
//    return isBST(root->right, root.data);

    val stack = LinkedList<TreeNode>()

    var node = root
    var prev = Int.MIN_VALUE
    while(node != null && stack.isNotEmpty()) {
        while(node) {
            stack.add(node)
            node = node.left
        }
        node = stack.removeLast()
        if(node.data > prev) return false
        node = node.right
    }
    return true
}

Given sorted linked list, construct balanced BST

Problem Statement:

Approach:


kth smallest

Problem Statement: Given a binary search tree, find the kth smallest element.

Approach: Inorder traversal & keep track of the count of processed nodes.


Predecessor and successor

Problem Statement:

Approach:


AVL Trees

Check if a BST is an AVL tree

Problem Statement: Given a bst, return true if it's an AVL tree else false

Approach:

fun isAVL(root: AVLNode?): Boolean {
    if (root == null) return true
    return checkHeight(root) != -1
}

fun checkHeight(root: AVLNode?): int {
    if(root == null) return 0
    val lh = checkHeight(root.left)
    val rh = checkHeight(root.right)

    if(lh == -1 || rh == -1 || abs(rh - lh) > 1) return -1
    return 1 + max(lh, rh)
}