mirror of
https://github.com/TheAlgorithms/Python.git
synced 2024-11-27 23:11:09 +00:00
211 lines
4.7 KiB
Python
211 lines
4.7 KiB
Python
|
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()
|