-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
210 additions
and
0 deletions.
There are no files selected for viewing
210 changes: 210 additions & 0 deletions
210
algorithm/data_structures/binary_tree/diff_views_of_binary_tree.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,210 @@ | ||
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() |