Bea.AI coding blog
  • Tree
    • Tree Traverse
    • Iteration based traverse
    • Typical problems and solutions
      • Max width of binary tree
      • Binary Tree & BST Serialize & Deserialize
      • Lowest common ancestor (LCA) for Binary Tree and BST
      • Subproblem-based Approach for Resolving Max Value on Trees
      • Path sum III
  • Graph
  • Data structure
    • Java data structure
  • Algorithm general templates
    • Tree
    • Trie
    • Graph
  • Java Algorithm Tips and Tricks
    • Java concurrent list
  • Coding patterns & Strategies
  • Coding patterns & template
    • 1. Binary Search
    • 2. Two Pointer
    • 3. Sliding Window
    • 4. Backtracking
    • 5. DFS
    • 6. BFS
    • 7. Stack
    • 8. Heap
    • 9. Prefix Sum
    • 10. Linked List
    • 11. BST
    • 12. Line sweep
    • 14. Tree
    • 15. Graph
    • 16. Bit manipulation
    • 17. Matrix
    • 18. Monotonic Stack
    • 19. Sorting
    • 20. Union Find
    • 21. Trie
    • 22. Dynamic programming
    • 23. Customized Data Structure
  • Code interview steps
  • Leetcode
    • Tree
      • Traversal
      • Construction and Conversion
      • Search and Validation
      • Manipulation and Modification
      • Special Trees
      • Miscellaneous
    • Dynamic programing
      • Classic DP Problems
      • Sequence/Array DP
      • Matrix DP
      • Knapsack Problems
      • String DP
      • Tree/Graph DP
      • Optimization Problems
      • Combinatorial DP
    • DFS
      • Graph Traversal
      • Path Finding
      • Tree Traversal
      • Backtracking
      • Topological Sorting
      • Traversal Order
      • Dynamic Programming with DFS
      • Connected Components
    • BFS
      • Graph
      • Tree
      • Matrix
      • String
      • Others
    • Two points
      • Array
      • String
      • Linked List
      • Sorting
      • Others
    • LinkedList
      • Basic Operations
      • Cycle Detection and Handling
      • Intersection and Union
      • Partitioning and Merging
      • Palindrome
      • Miscellaneous
    • Backtracking
    • Binary Search
    • Union Find
    • Trie
    • Sort
    • Heap
    • Randomness
    • Topological sort
    • Stack
    • HashTable
    • Sliding Window
  • Blind 75
    • Array
    • Binary
    • Dynamic Programming
    • Graph
    • Interval
    • LinkedList
    • Matrix
    • String
    • Tree
    • Heap
  • Companies
    • Apple
Powered by GitBook
On this page
  • 6. Binary Tree Level Order Traversal
  • 7. Minimum Depth of Binary Tree
  • 8. Binary Tree Right Side View
  • 9. Populating Next Right Pointers in Each Node
  1. Leetcode
  2. BFS

Tree

6. Binary Tree Level Order Traversal

  1. Problem Description: The problem "Binary Tree Level Order Traversal" on LeetCode asks us to return the level order traversal of a binary tree. The level order traversal means visiting nodes in a tree level by level, from left to right.

LeetCode link for the problem: https://leetcode.com/problems/binary-tree-level-order-traversal/

  1. Optimized Java Solution with Detailed Comments:

import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.Queue;

class Solution { public List<List> levelOrder(TreeNode root) { // List to store the level order traversal List<List> result = new ArrayList<>();

    // Base case: If the tree is empty, return the empty list
    if (root == null) {
        return result;
    }
    
    // Use a queue to perform a level order traversal
    Queue<TreeNode> queue = new LinkedList<>();
    // Add the root node to the queue
    queue.offer(root);
    
    // Continue the traversal until the queue is empty
    while (!queue.isEmpty()) {
        // Get the size of the current level
        int levelSize = queue.size();
        // List to store the values of the current level
        List<Integer> levelValues = new ArrayList<>();
        
        // Process all nodes in the current level
        for (int i = 0; i < levelSize; i++) {
            TreeNode current = queue.poll();
            levelValues.add(current.val);
            
            // Add the left and right children of the current node to the queue
            if (current.left != null) {
                queue.offer(current.left);
            }
            if (current.right != null) {
                queue.offer(current.right);
            }
        }
        
        // Add the values of the current level to the result list
        result.add(levelValues);
    }
    
    // Return the level order traversal
    return result;
}

}

  1. Algorithm and Interview Tips:

The problem can be solved using a breadth-first search (BFS) approach, where we traverse the tree level by level. Here is a step-by-step breakdown of the algorithm:

  • First, we initialize an empty list called result to store the level order traversal.

  • We handle the base case where the root is null. In this case, we simply return the empty result list.

  • Next, we initialize a queue to hold the nodes of the tree. We add the root node to the queue.

  • We start a while loop that continues until the queue is empty.

  • Inside the loop, we get the size of the current level by using the queue's size() method. This will give us the number of nodes at the current level.

  • We also create an empty list called levelValues to store the values of the nodes at the current level.

  • We iterate over the current level by using a for loop from 0 to the level size.

  • In each iteration, we:

    • Remove the first node from the queue by using the poll() method.

    • Add the value of the current node to the levelValues list.

    • Add the left and right children of the current node to the queue if they exist.

  • After processing all nodes in the current level, we add the levelValues list to the result list.

  • Finally, we return the result list, which contains the level order traversal of the binary tree.

During the interview, it's important to communicate your approach and algorithms clearly. The BFS approach is often the most intuitive and efficient solution for level order traversal. Make sure to explain the complexity of the algorithm as O(N), where N is the number of nodes in the tree.

7. Minimum Depth of Binary Tree

  1. Problem Description:

The problem "Minimum Depth of Binary Tree" is to find the minimum depth of a binary tree. The minimum depth is defined as the number of nodes along the shortest path from the root node to the nearest leaf node.

Leetcode Link: https://leetcode.com/problems/minimum-depth-of-binary-tree/

  1. Optimized Java Code:

Below is the optimized Java solution for the "Minimum Depth of Binary Tree" problem:


/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public int minDepth(TreeNode root) {
        if(root == null) return 0; 
        
        //Create base case for leaf nodes
        if(root.left == null && root.right == null) return 1; 
        
        int leftDepth = root.left != null ? minDepth(root.left) : Integer.MAX_VALUE;
        int rightDepth = root.right != null ? minDepth(root.right) : Integer.MAX_VALUE;
        
        return 1 + Math.min(leftDepth, rightDepth);
    }
}
  1. Detailed Description:

The problem can be solved using a recursive algorithm. The intuition behind the algorithm is to find the minimum depth of the left and right sub-trees, and then choose the smaller depth and add 1 to it to get the minimum depth of the whole tree.

The algorithm works as follows:

  • If the root is null, the tree is empty, so the minimum depth is 0. Return 0.

  • If both the left and right children of the root are null, then we have reached a leaf node. Return 1.

  • Otherwise, recursively find the minimum depth of the left and right sub-trees.

  • If the left child is null, we only need to consider the right child. Find the minimum depth of the right sub-tree using recursion, and assign it to the rightDepth variable.

  • If the right child is null, we only need to consider the left child. Find the minimum depth of the left sub-tree using recursion, and assign it to the leftDepth variable.

  • If both the left and right children are present, find the minimum depth of both sub-trees using recursion, and assign them to the respective variables.

  • Finally, return 1 + the minimum of leftDepth and rightDepth. This gives us the minimum depth of the whole tree.

During the interview process, it's important to communicate your thought process clearly and step through the algorithm to the interviewer. Explain the base cases, how the recursion works, and how the minimum depth is calculated. Additionally, you can mention the time complexity of the algorithm, which is O(n) as it visits each node once, where n is the number of nodes in the binary tree.

8. Binary Tree Right Side View

  1. Problem Description: The problem "Binary Tree Right Side View" is described on LeetCode here: https://leetcode.com/problems/binary-tree-right-side-view/

Given a binary tree, imagine yourself standing on the right side of it, return the values of the nodes you can see ordered from top to bottom.

  1. Optimized Java Code with Detailed Comments:

import java.util.*;

public class Solution {
    public List<Integer> rightSideView(TreeNode root) {
        List<Integer> result = new ArrayList<>();

        if (root == null) return result; // Edge case: empty tree

        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root);

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

            for (int i = 0; i < levelSize; i++) {
                TreeNode current = queue.poll();
                rightmostValue = current.val; // Update the rightmost value at each level

                if (current.left != null) {
                    queue.offer(current.left);
                }
                if (current.right != null) {
                    queue.offer(current.right);
                }
            }

            result.add(rightmostValue);
        }

        return result;
    }
}
  1. Detailed Description of the Algorithm:

  • We use a level-order traversal approach using a queue to process the nodes of the tree.

  • We start with the root node, add it to the queue, and iterate until the queue becomes empty.

  • For each level, we calculate the size of the queue at the beginning (levelSize) to process only the nodes at that level.

  • We also initialize a variable rightmostValue to store the value of the rightmost node at each level. We update this value at each iteration of the level.

  • Inside the level iteration, we extract the current node from the queue and update the rightmostValue with its value.

  • Then we check if the current node has left and right children. If yes, we add them to the queue for the next level.

  • Finally, after processing all nodes at the current level, we add rightmostValue to the result list.

  • Once the level-order traversal is complete, we return the result list containing the values of the right side view nodes from top to bottom.

During the interview process, it's essential to communicate your approach and code clearly. Explaining the algorithm step-by-step and adding comments to the code helps the interviewer understand your thought process. Remember to consider edge cases, optimize your code, and validate it with test cases.

9. Populating Next Right Pointers in Each Node

  1. The problem "Populating Next Right Pointers in Each Node" on LeetCode can be found at the following link: https://leetcode.com/problems/populating-next-right-pointers-in-each-node/

  2. Here is the optimized Java code for the problem with detailed comments:

class Node {
    public int val;
    public Node left;
    public Node right;
    public Node next;

    public Node(int val) {
        this.val = val;
    }
}

class Solution {
    public Node connect(Node root) {
        if (root == null) return null;

        Node leftmost = root; // Keep track of the leftmost node in each level

        while (leftmost.left != null) {
            Node head = leftmost; // Head node of the current level

            while (head != null) {
                // Set next pointers of the nodes of the current level
                head.left.next = head.right;
                if (head.next != null) {
                    head.right.next = head.next.left;
                }

                head = head.next; // Move to the next node in the current level
            }

            leftmost = leftmost.left; // Move to the leftmost node of the next level
        }

        return root;
    }
}
  1. Algorithm explanation and thought process:

The problem asks us to populate each node's next pointer with the node to its right in the same level. The tree is a perfect binary tree, which means every level except the last level will be completely filled, and all nodes are populated from left to right.

To solve this problem, we can utilize a modified level order traversal technique. We start from the root node and iterate level by level. At each level, we traverse the nodes and set their next pointers accordingly.

We maintain a variable leftmost to keep track of the leftmost node in each level. We initially set it to the root node. Then, we enter a while loop that runs until we reach the last level (i.e. when the leftmost node doesn't have a left child).

Inside the while loop, we have another loop that iterates through the nodes of the current level. We use a variable head to keep track of the current node. We set the next pointer of the left child of head to its right child. If head has a next pointer (i.e. it's not the rightmost node in its level), we set the next pointer of the right child of head to the left child of its next pointer.

We then move head to its next node in the current level and repeat the process until we reach the end of the level. Once we finish processing the current level, we move leftmost to its left child to move to the next level.

By following this approach, we can efficiently set the next pointers of all the nodes in the tree. At each level, we use the next pointers set in the previous level to navigate to the next level and form the required connections.

During the interview process, it is important to understand the problem requirements, come up with an algorithm that solves it efficiently, and write clean and readable code. Explaining the thought process and the rationale behind the solution is equally important.

PreviousGraphNextMatrix

Last updated 1 year ago