mirror of
https://github.com/TheAlgorithms/Python.git
synced 2024-11-23 21:11:08 +00:00
[Binary Tree] Different views of binary tree added (#6965)
* 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>
This commit is contained in:
parent
0c7c5fa7b0
commit
3448ae5cec
210
data_structures/binary_tree/diff_views_of_binary_tree.py
Normal file
210
data_structures/binary_tree/diff_views_of_binary_tree.py
Normal file
|
@ -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()
|
Loading…
Reference in New Issue
Block a user