Given the root of a binary tree, implement two functions: one to serialize the tree into a string and one to deserialize that string back into the original binary tree. The encoding must preserve both node values and tree structure, including missing children.
Example 1:
Input: root = [1,2,3,null,null,4,5]
Output: serialized = "1,2,3,#,#,4,5,#,#,#,#"
Explanation: The string stores nodes in level-order and uses `#` for null children.
Example 2:
Input: root = []
Output: serialized = "#"
Explanation: An empty tree is represented by a single null marker.
0 <= number of nodes <= 10^4-1000 <= Node.val <= 1000