mirror of
https://github.com/TheAlgorithms/Python.git
synced 2024-11-27 15:01:08 +00:00
3448ae5cec
* Different views of binary tree added * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * mypy errors resolved * doc test for remaining functions * Flake8 comments resolved * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Example moved in if block * doctest cases added * Cases from if block removed * Update data_structures/binary_tree/diff_views_of_binary_tree.py Co-authored-by: Christian Clauss <cclauss@me.com> * Update data_structures/binary_tree/diff_views_of_binary_tree.py Co-authored-by: Christian Clauss <cclauss@me.com> * PR Comments resolved * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * flake8 warning resolved * Changes revered * flake8 issue resolved * Put the diagrams just above the doctests * Update diff_views_of_binary_tree.py * Update diff_views_of_binary_tree.py * I love mypy * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Christian Clauss <cclauss@me.com>
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()
|