# TODO: 545. Boundary of Binary Tree

## Problem

<figure><img src="https://1388126071-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MVQ7Ie-PZpN_8yApX0-%2Fuploads%2F9yH0VjeCgOAJj3wNDpXH%2FScreenshot%202024-03-30%20at%2011.13.45.png?alt=media&#x26;token=6e0230ba-7046-47d7-ad29-c84502adab00" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1388126071-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MVQ7Ie-PZpN_8yApX0-%2Fuploads%2FxbhuJGgrrcpn2QhO9M1L%2FScreenshot%202024-03-30%20at%2011.14.02.png?alt=media&#x26;token=9635a72f-29c6-49b9-a3c6-2b0d273a60e8" alt=""><figcaption></figcaption></figure>

<figure><img src="https://1388126071-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MVQ7Ie-PZpN_8yApX0-%2Fuploads%2FvuDnh9gEtrUbEXfr3nwl%2FScreenshot%202024-03-30%20at%2011.14.24.png?alt=media&#x26;token=352aab6c-24a7-4ada-9608-b10d8bea48be" alt=""><figcaption></figcaption></figure>

## Intuition

## Time Complexity

`O(N)`&#x20;

In worst case, we might need to explore all the nodes

## Space Complexity

`O(1)`

Auxiliary space complexity

## Solution

```java
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<Integer> boundaryOfBinaryTree(TreeNode root) {
        // TC: O(N), N->Number of nodes
        // SC: Auxillary space complexity
        List<Integer> result = new ArrayList<>();

        if(root == null) {
            return result;
        }

        // Add this condition to add root value, incase of single node tree,
        // this condition is failed and is caught in addLeaves
        if(!isLeaf(root)) {
            result.add(root.val);
        }

        // According to the boundary definition, left + leaves + right
        addLeftBoundary(root, result);
        addLeaves(root, result);
        addRightBoundary(root, result);

        return result;
    }

    private boolean isLeaf(TreeNode node) {
        return node.left == null && node.right == null;
    }

    private void addLeftBoundary(TreeNode root, List<Integer> result) {
        TreeNode node = root.left;
        
        // Explore left most nodes in left subtree from root
        while(node != null) {
            // Add the values only if it is not a leaf node
            if(!isLeaf(node)) result.add(node.val);

            // Explore towards left 
            if(node.left != null) node = node.left;
            else node = node.right; // In case if left does not exit, explore right
        }
    }

    private void addLeaves(TreeNode node, List<Integer> result) {
        if(node == null) return;
        
        // This can be acheived by any DFS, Used pre order here
        // with condition that node should be leaf
        if(isLeaf(node)) result.add(node.val);

        if(node.left!=null) addLeaves(node.left, result);
        if(node.right!=null) addLeaves(node.right, result);
    }

    private void addRightBoundary(TreeNode root, List<Integer> result) {
        TreeNode node = root.right;
        // Same as adding left boundary, but since we are moving the border
        // anti-clockwise, reverse the order of insertion using LinkedList
        List<Integer> current = new LinkedList<>();
        
        while(node != null) {
            // Add the values only if it is not a leaf node
            if(!isLeaf(node)) current.addFirst(node.val);

            // Explore towards right
            if(node.right != null) node = node.right;
            else node = node.left; // In case if right does not exit, explore left
        }
        // Add all the linkedlist values to result
        for(int nodeVal: current) result.add(nodeVal);
    }
}
```
