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
  • 26. Binary Tree Zigzag Level Order Traversal (103)
  • 27. Flatten Binary Tree to Linked List (114)
  • 28. Binary Tree Level Order Traversal (102)
  • 29. Populating Next Right Pointers in Each Node (116)
  • 30. Binary Tree Right Side View (199)
  1. Leetcode
  2. DFS

Traversal Order

26. Binary Tree Zigzag Level Order Traversal (103)

  1. Problem Description: The problem "Binary Tree Zigzag Level Order Traversal" asks us to traverse a binary tree in a zigzag pattern, where we visit the nodes level by level. For each level, we alternate between starting from the leftmost node and starting from the rightmost node. We need to return the zigzag level order traversal of the binary tree.

Problem Link: https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/

  1. Optimized Java Code with Detailed Comments:

import java.util.*;

class Solution {
    public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
        // Initialize the result list
        List<List<Integer>> zigzagList = new ArrayList<>();

        // Edge case: if the root is null, return an empty list
        if (root == null) {
            return zigzagList;
        }

        // Create a queue to perform level order traversal
        Queue<TreeNode> queue = new LinkedList<>();

        // Add the root node to the queue
        queue.offer(root);

        // Variable to keep track of the level
        int level = 0;

        // Perform level order traversal
        while (!queue.isEmpty()) {
            // Get the number of nodes at each level
            int levelSize = queue.size();

            // Create a temporary list to store the elements for the current level
            List<Integer> tempList = new ArrayList<>();

            for (int i = 0; i < levelSize; i++) {
                // Remove the node from the queue
                TreeNode currentNode = queue.poll();

                // Add the node's value to the temporary list
                tempList.add(currentNode.val);

                // Check if the node has left and right children, and add them to the queue if available
                if (currentNode.left != null) {
                    queue.offer(currentNode.left);
                }
                if (currentNode.right != null) {
                    queue.offer(currentNode.right);
                }
            }

            // If the level is odd, reverse the order of the temporary list
            if (level % 2 == 1) {
                Collections.reverse(tempList);
            }

            // Add the temporary list to the result list
            zigzagList.add(tempList);

            // Increment the level
            level++;
        }

        // Return the zigzag level order traversal
        return zigzagList;
    }
}
  1. Detailed Description and Algorithm Explanation:

To solve this problem, we can use a modified version of the level order traversal algorithm. The modified algorithm will traverse the tree level by level, but for each level, it will alternate between starting from the leftmost node and starting from the rightmost node.

Here is a step-by-step algorithm:

  1. Initialize the result list zigzagList as an empty list.

  2. Edge case: Check if the root is null. If so, return an empty list.

  3. Create a queue to perform level order traversal. We can use the built-in LinkedList class as the implementation.

  4. Add the root node to the queue using the offer() method.

  5. Initialize a variable level as 0 to keep track of the current level.

  6. Perform level order traversal until the queue is empty.

  7. Get the number of nodes at the current level using the queue's size.

  8. Create a temporary list tempList to store the elements for the current level.

  9. Iterate a loop i from 0 to levelSize - 1:

    a. Remove the node from the queue using the poll() method.

    b. Add the node's value to the tempList.

    c. Check if the node has left and right children, and add them to the queue if available.

  10. If the level is odd (i.e., level % 2 == 1), reverse the order of the tempList using the Collections.reverse() method.

  11. Add the tempList to the zigzagList.

  12. Increment the level by 1.

  13. Return the zigzagList.

During an interview process, it is important to approach this problem by breaking it down into smaller steps, starting with a basic level order traversal and then modifying the algorithm to achieve the zigzag pattern. It is also crucial to consider edge cases, such as when the root is null, and to check the requirements and constraints given in the problem statement.

27. Flatten Binary Tree to Linked List (114)

  1. Problem Description: The problem "Flatten Binary Tree to Linked List" (114) on LeetCode asks us to flatten a binary tree into a linked list in place. The flattened tree should follow the right pointers of each node, and the left pointers should point to null. We need to modify the original tree in place without using extra space.

LeetCode link: https://leetcode.com/problems/flatten-binary-tree-to-linked-list/

  1. Optimized Java Code:

class Solution {
    public void flatten(TreeNode root) {
        if (root == null) {
            return;
        }
        
        // Flatten the left subtree
        flatten(root.left);
        
        // Flatten the right subtree
        flatten(root.right);
        
        // Store the right subtree in a temporary variable
        TreeNode temp = root.right;
        
        // Move the left subtree to become the right subtree
        root.right = root.left;
        root.left = null;
        
        // Find the end of the new right subtree and attach the previous right subtree to it
        TreeNode current = root;
        while (current.right != null) {
            current = current.right;
        }
        current.right = temp;
    }
}
  1. Description of the algorithm and thinking process during the interview:

To solve this problem, we can use a recursive approach. The basic idea is to flatten the left subtree and the right subtree separately, and then attach the flattened right subtree to the end of the flattened left subtree.

In the code, we define a recursive function flatten that takes a TreeNode as input. We check if the current node is null, and if so, we simply return.

Next, we recursively call the flatten function on the left and right subtrees. This ensures that both the left and right subtrees are flattened properly.

After flattening the left and right subtrees, we store the right subtree in a temporary variable temp.

We then move the entire left subtree to the right side of the current node by assigning root.right = root.left and setting root.left to null.

Lastly, we traverse the new right subtree to find its end. We start from the root and keep moving to the right until we reach a node whose right child is null. At that point, we attach the previous right subtree (temp) to the right of the current node.

Overall, this algorithm performs a post-order traversal of the binary tree and modifies the tree in place to flatten it into a linked list structure. This approach requires O(n) time complexity as we need to visit each node once, and O(h) space complexity for the recursive call stack, where h is the height of the tree.

28. Binary Tree Level Order Traversal (102)

  1. Problem Description: The problem is to perform a level order traversal of a binary tree and return the results as a list of lists, where each inner list represents the nodes at a specific level of the tree.

Leetcode Link: https://leetcode.com/problems/binary-tree-level-order-traversal/

  1. Optimized Java Solution with Comments:

// Definition for a binary tree node.
class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    TreeNode(int val) {
        this.val = val;
    }
}

class Solution {
    public List<List<Integer>> levelOrder(TreeNode root) {
        List<List<Integer>> result = new ArrayList<>();
        
        // Base case: if the root is null, return an empty result list
        if (root == null) {
            return result;
        }
        
        // Use a queue to store the nodes in the current level
        Queue<TreeNode> queue = new LinkedList<>();
        queue.offer(root); // Add the root node to the queue
        
        while (!queue.isEmpty()) {
            int levelSize = queue.size(); // Get the current level size
            List<Integer> currentLevel = new ArrayList<>();
            
            // Process all nodes in the current level
            for (int i = 0; i < levelSize; i++) {
                TreeNode currentNode = queue.poll(); // Remove and return the front of the queue
                currentLevel.add(currentNode.val); // Add the current node's value to the current level list
                
                // Add the current node's children to the queue if they exist
                if (currentNode.left != null) {
                    queue.offer(currentNode.left);
                }
                if (currentNode.right != null) {
                    queue.offer(currentNode.right);
                }
            }
            
            result.add(currentLevel); // Add the current level list to the result list
        }
        
        return result;
    }
}
  1. Algorithm and Interview Process:

The problem requires performing a level order traversal of a binary tree. In level order traversal, we visit nodes of the tree level by level, from top to bottom and left to right.

To solve this problem efficiently, we can use a queue data structure. We start with a queue containing the root node. Then, we iterate until the queue becomes empty. In each iteration, we process all the nodes in the current level by removing them from the queue, adding their values to the current level list, and enqueuing their children (if any). Finally, we add the current level list to the result list and continue the process until the queue becomes empty.

During the interview process, it's important to have a clear understanding of the problem requirements and constraints. Consider asking clarifying questions if needed. One approach to solving this problem is to walk the interviewer through the algorithm step by step, explaining the rationale behind each step and discussing the time and space complexity. Additionally, you can discuss possible edge cases and how you would handle them in the implementation. By demonstrating your problem-solving skills, efficient coding, and clear communication, you can showcase your expertise in solving LeetCode problems.

29. Populating Next Right Pointers in Each Node (116)

  1. Problem Description:

The problem "Populating Next Right Pointers in Each Node" is a binary tree problem where we are given a binary tree with the following structure:

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

Our task is to populate the next pointers such that they point to the next node on the same level in the binary tree. The next pointer for each node should be set to null initially.

We need to solve this problem in constant space, meaning we are not allowed to use any extra space for additional data structures.

LeetCode link: https://leetcode.com/problems/populating-next-right-pointers-in-each-node/

  1. Optimized Java code for the problem "Populating Next Right Pointers in Each Node":

class Solution {
    public Node connect(Node root) {
        if (root == null) {
            return null;
        }
        
        Node leftmost = root;
        
        while (leftmost.left != null) {
            Node curr = leftmost;
            
            while (curr != null) {
                curr.left.next = curr.right;
                
                if (curr.next != null) {
                    curr.right.next = curr.next.left;
                }
                
                curr = curr.next;
            }
            
            leftmost = leftmost.left;
        }
        
        return root;
    }
}
  1. Detailed Description and Algorithm:

The problem can be solved using a modified level order traversal. We initialize the leftmost pointer to the root of the tree.

Then, we iterate over each level of the tree starting from the top level (root). For each level, we have an outer loop that keeps track of the leftmost node of the current level (leftmost) and an inner loop that traverses all the nodes of the current level (curr).

Inside the inner loop, we set the next pointer of the left child of the current node to its right child. This takes care of connecting the adjacent nodes on the same level.

Then, we check if the current node has a next pointer. If it does, we set the next pointer of the right child of the current node to the left child of the next node. This takes care of connecting nodes on different branches at the same level.

After finishing the inner loop for the current level, we move leftmost pointer to the left child of the current leftmost node, and repeat the process for the next level.

Finally, we return the root of the modified binary tree with the next pointers properly set.

During an interview, it would be helpful to clarify any doubts with the interviewer to ensure a correct understanding of the problem. Then, explain the approach mentioned above, step-by-step. Show your thinking process, explain the purpose of each step, and highlight any optimizations made. It's also a good idea to discuss the time and space complexity of the solution.

30. Binary Tree Right Side View (199)

  1. Problem Description: The problem "Binary Tree Right Side View" asks us to return the values of the nodes on the right side of a binary tree, viewed from top to bottom. The problem can be found on LeetCode at the following link: https://leetcode.com/problems/binary-tree-right-side-view/

  2. Optimized Java Code with Detailed Comments:

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

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    TreeNode(int val) {
        this.val = val;
    }
}

public class BinaryTreeRightSideView {
    public List<Integer> rightSideView(TreeNode root) {
        List<Integer> result = new ArrayList<>(); // to store the right side view
        if (root == null) {
            return result;
        }

        Queue<TreeNode> queue = new LinkedList<>(); // to perform level order traversal
        queue.offer(root);

        while (!queue.isEmpty()) {
            int levelSize = queue.size(); // number of nodes at current level

            for (int i = 0; i < levelSize; i++) {
                TreeNode current = queue.poll();

                if (i == levelSize - 1) {
                    result.add(current.val); // last node at current level, add to result
                }

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

        return result;
    }
}
  1. Algorithm and Thought Process:

  • The problem asks for the values on the right side of the binary tree, viewed from top to bottom. To solve this problem, we can perform a level order traversal of the tree and add only the last node at each level to the result.

  • We start by initializing an empty queue and adding the root node to the queue.

  • We iterate until the queue is empty. Inside the loop, we retrieve the number of nodes at the current level.

  • We iterate through the current level nodes. If the current node is the last node at the current level, we add its value to the result list.

  • For each node, if it has a left child, we add it to the queue. Similarly, if it has a right child, we add it to the queue.

  • Finally, we return the result list containing the values on the right side of the binary tree.

  • During the interview process, it is important to understand the problem requirements and constraints. Drawing out the binary tree and performing an example run on paper can help visualize the problem and come up with a plan.

  • The optimized solution provided uses a queue to perform level order traversal and maintains a separate result list to store the values on the right side of the tree.

  • The time complexity of this solution is O(N), where N is the number of nodes in the binary tree. We need to visit each node once.

  • The space complexity is O(M), where M is the maximum number of nodes at any level in the binary tree. In the worst case, the maximum number of nodes at a level could be N/2.

  • It is important to handle edge cases, such as when the root is null, and return early to avoid unnecessary computations.

By following this approach and understanding the problem requirements, you can effectively solve the "Binary Tree Right Side View" problem on LeetCode and handle similar tree traversal problems during interviews.

PreviousTopological SortingNextDynamic Programming with DFS

Last updated 1 year ago