r""" Problem: Given root of a binary tree, return the: 1. binary-tree-right-side-view 2. binary-tree-left-side-view 3. binary-tree-top-side-view 4. binary-tree-bottom-side-view """ from __future__ import annotations from collections import defaultdict from dataclasses import dataclass @dataclass class TreeNode: val: int left: TreeNode | None = None right: TreeNode | None = None def make_tree() -> TreeNode: """ >>> make_tree().val 3 """ return TreeNode(3, TreeNode(9), TreeNode(20, TreeNode(15), TreeNode(7))) def binary_tree_right_side_view(root: TreeNode) -> list[int]: r""" Function returns the right side view of binary tree. 3 <- 3 / \ 9 20 <- 20 / \ 15 7 <- 7 >>> binary_tree_right_side_view(make_tree()) [3, 20, 7] >>> binary_tree_right_side_view(None) [] """ def depth_first_search( root: TreeNode | None, depth: int, right_view: list[int] ) -> None: """ A depth first search preorder traversal to append the values at right side of tree. """ if not root: return if depth == len(right_view): right_view.append(root.val) depth_first_search(root.right, depth + 1, right_view) depth_first_search(root.left, depth + 1, right_view) right_view: list = [] if not root: return right_view depth_first_search(root, 0, right_view) return right_view def binary_tree_left_side_view(root: TreeNode) -> list[int]: r""" Function returns the left side view of binary tree. 3 -> 3 / \ 9 -> 9 20 / \ 15 -> 15 7 >>> binary_tree_left_side_view(make_tree()) [3, 9, 15] >>> binary_tree_left_side_view(None) [] """ def depth_first_search( root: TreeNode | None, depth: int, left_view: list[int] ) -> None: """ A depth first search preorder traversal to append the values at left side of tree. """ if not root: return if depth == len(left_view): left_view.append(root.val) depth_first_search(root.left, depth + 1, left_view) depth_first_search(root.right, depth + 1, left_view) left_view: list = [] if not root: return left_view depth_first_search(root, 0, left_view) return left_view def binary_tree_top_side_view(root: TreeNode) -> list[int]: r""" Function returns the top side view of binary tree. 9 3 20 7 ⬇ ⬇ ⬇ ⬇ 3 / \ 9 20 / \ 15 7 >>> binary_tree_top_side_view(make_tree()) [9, 3, 20, 7] >>> binary_tree_top_side_view(None) [] """ def breadth_first_search(root: TreeNode, top_view: list[int]) -> None: """ A breadth first search traversal with defaultdict ds to append the values of tree from top view """ queue = [(root, 0)] lookup = defaultdict(list) while queue: first = queue.pop(0) node, hd = first lookup[hd].append(node.val) if node.left: queue.append((node.left, hd - 1)) if node.right: queue.append((node.right, hd + 1)) for pair in sorted(lookup.items(), key=lambda each: each[0]): top_view.append(pair[1][0]) top_view: list = [] if not root: return top_view breadth_first_search(root, top_view) return top_view def binary_tree_bottom_side_view(root: TreeNode) -> list[int]: r""" Function returns the bottom side view of binary tree 3 / \ 9 20 / \ 15 7 ↑ ↑ ↑ ↑ 9 15 20 7 >>> binary_tree_bottom_side_view(make_tree()) [9, 15, 20, 7] >>> binary_tree_bottom_side_view(None) [] """ from collections import defaultdict def breadth_first_search(root: TreeNode, bottom_view: list[int]) -> None: """ A breadth first search traversal with defaultdict ds to append the values of tree from bottom view """ queue = [(root, 0)] lookup = defaultdict(list) while queue: first = queue.pop(0) node, hd = first lookup[hd].append(node.val) if node.left: queue.append((node.left, hd - 1)) if node.right: queue.append((node.right, hd + 1)) for pair in sorted(lookup.items(), key=lambda each: each[0]): bottom_view.append(pair[1][-1]) bottom_view: list = [] if not root: return bottom_view breadth_first_search(root, bottom_view) return bottom_view if __name__ == "__main__": import doctest doctest.testmod()