11from __future__ import annotations
22
3+ from collections .abc import Iterator
4+ from dataclasses import dataclass
35
6+
7+ @dataclass
48class TreeNode :
59 """
610 A binary tree node has a value, left child, and right child.
711
812 Props:
9- val(int) : The value of the node.
13+ value : The value of the node.
1014 left: The left child of the node.
1115 right: The right child of the node.
1216 """
1317
14- def __init__ (
15- self ,
16- val : int = 0 ,
17- left : TreeNode | None = None ,
18- right : TreeNode | None = None ,
19- ) -> None :
20- if not isinstance (val , int ):
21- raise TypeError ("Value must be an integer." )
22- self .val = val
23- self .left = left
24- self .right = right
25-
26-
27- # Helper functions
28- def are_trees_identical (root1 : TreeNode | None , root2 : TreeNode | None ) -> bool :
29- """
30- Check if two binary trees are identical.
31-
32- Args:
33- root1 (TreeNode): Tree 1
34- root2 (TreeNode): Tree 2
35-
36- Returns:
37- bool: True if the trees are identical, False otherwise.
38-
39- >>> root1 = TreeNode(1)
40- >>> root1.left = TreeNode(2)
41- >>> root1.right = TreeNode(3)
42- >>> root2 = TreeNode(1)
43- >>> root2.left = TreeNode(2)
44- >>> root2.right = TreeNode(3)
45- >>> are_trees_identical(root1, root2)
46- True
47- >>> root1 = TreeNode(1)
48- >>> root1.left = TreeNode(2)
49- >>> root1.right = TreeNode(3)
50- >>> root2 = TreeNode(1)
51- >>> root2.left = TreeNode(2)
52- >>> root2.right = TreeNode(4)
53- >>> are_trees_identical(root1, root2)
54- False
55- """
56-
57- if not root1 and not root2 :
58- return True
59- if not root1 or not root2 :
60- return False
61-
62- return (
63- root1 .val == root2 .val
64- and are_trees_identical (root1 .left , root2 .left )
65- and are_trees_identical (root1 .right , root2 .right )
66- )
18+ value : int = 0
19+ left : TreeNode | None = None
20+ right : TreeNode | None = None
6721
22+ def __post_init__ (self ):
23+ if not isinstance (self .value , int ):
24+ raise TypeError ("Value must be an integer." )
6825
69- # Main functions
70- def serialize (root : TreeNode | None ) -> str :
71- """
72- Serialize a binary tree to a string using preorder traversal.
73-
74- Args:
75- root(TreeNode): The root of the binary tree.
76-
77- Returns:
78- A string representation of the binary tree.
79-
80- >>> root = TreeNode(1)
81- >>> root.left = TreeNode(2)
82- >>> root.right = TreeNode(3)
83- >>> root.right.left = TreeNode(4)
84- >>> root.right.right = TreeNode(5)
85- >>> serialize(root)
86- '1,2,null,null,3,4,null,null,5,null,null'
87- >>> root = TreeNode(1)
88- >>> serialize(root)
89- '1,null,null'
90- """
91-
92- # Use "null" to represent empty nodes in the serialization
93- if not root :
94- return "null"
95-
96- return str (root .val ) + "," + serialize (root .left ) + "," + serialize (root .right )
26+ def __iter__ (self ) -> Iterator [TreeNode ]:
27+ """
28+ Iterate through the tree in preorder.
29+
30+ Returns:
31+ An iterator of the tree nodes.
32+
33+ >>> list(TreeNode(1))
34+ [1,null,null]
35+ >>> tuple(TreeNode(1, TreeNode(2), TreeNode(3)))
36+ (1,2,null,null,3,null,null, 2,null,null, 3,null,null)
37+ """
38+ yield self
39+ yield from self .left or ()
40+ yield from self .right or ()
41+
42+ def __len__ (self ) -> int :
43+ """
44+ Count the number of nodes in the tree.
45+
46+ Returns:
47+ The number of nodes in the tree.
48+
49+ >>> len(TreeNode(1))
50+ 1
51+ >>> len(TreeNode(1, TreeNode(2), TreeNode(3)))
52+ 3
53+ """
54+ return sum (1 for _ in self )
55+
56+ def __repr__ (self ) -> str :
57+ """
58+ Represent the tree as a string.
59+
60+ Returns:
61+ A string representation of the tree.
62+
63+ >>> repr(TreeNode(1))
64+ '1,null,null'
65+ >>> repr(TreeNode(1, TreeNode(2), TreeNode(3)))
66+ '1,2,null,null,3,null,null'
67+ >>> repr(TreeNode(1, TreeNode(2), TreeNode(3, TreeNode(4), TreeNode(5))))
68+ '1,2,null,null,3,4,null,null,5,null,null'
69+ """
70+ return f"{ self .value } ,{ self .left !r} ,{ self .right !r} " .replace ("None" , "null" )
71+
72+ @classmethod
73+ def five_tree (cls ) -> TreeNode :
74+ """
75+ >>> repr(TreeNode.five_tree())
76+ '1,2,null,null,3,4,null,null,5,null,null'
77+ """
78+ root = TreeNode (1 )
79+ root .left = TreeNode (2 )
80+ root .right = TreeNode (3 )
81+ root .right .left = TreeNode (4 )
82+ root .right .right = TreeNode (5 )
83+ return root
9784
9885
9986def deserialize (data : str ) -> TreeNode | None :
@@ -106,44 +93,42 @@ def deserialize(data: str) -> TreeNode | None:
10693 Returns:
10794 The root of the binary tree.
10895
109- >>> root = TreeNode(1)
110- >>> root.left = TreeNode(2)
111- >>> root.right = TreeNode(3)
112- >>> root.right.left = TreeNode(4)
113- >>> root.right.right = TreeNode(5)
114- >>> serialzed_data = serialize(root)
96+ >>> root = TreeNode.five_tree()
97+ >>> serialzed_data = repr(root)
11598 >>> deserialized = deserialize(serialzed_data)
116- >>> are_trees_identical( root, deserialized)
99+ >>> root == deserialized
117100 True
118- >>> root = TreeNode(1)
119- >>> serialzed_data = serialize(root)
120- >>> dummy_data = "1,2,null,null,3,4,null,null,5,null,null"
121- >>> deserialized = deserialize(dummy_data)
122- >>> are_trees_identical(root, deserialized)
101+ >>> root is deserialized # two separate trees
102+ False
103+ >>> root.right.right.value = 6
104+ >>> root == deserialized
123105 False
106+ >>> serialzed_data = repr(root)
107+ >>> deserialized = deserialize(serialzed_data)
108+ >>> root == deserialized
109+ True
124110 >>> deserialize("")
125111 Traceback (most recent call last):
126112 ...
127113 ValueError: Data cannot be empty.
128114 """
129115
130- if data == "" :
116+ if not data :
131117 raise ValueError ("Data cannot be empty." )
132118
133- # Split the serialized string by comma to get node values
119+ # Split the serialized string by a comma to get node values
134120 nodes = data .split ("," )
135121
136122 def build_tree () -> TreeNode | None :
137123 # Get the next value from the list
138- val = nodes .pop (0 )
124+ value = nodes .pop (0 )
139125
140- if val == "null" :
126+ if value == "null" :
141127 return None
142128
143- node = TreeNode (int (val ))
129+ node = TreeNode (int (value ))
144130 node .left = build_tree () # Recursively build left subtree
145131 node .right = build_tree () # Recursively build right subtree
146-
147132 return node
148133
149134 return build_tree ()
0 commit comments