# Question

Formatted question description: https://leetcode.ca/all/297.html

Serialization is the process of converting a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network connection link to be reconstructed later in the same or another computer environment.

Design an algorithm to serialize and deserialize a binary tree. There is no restriction on how your serialization/deserialization algorithm should work. You just need to ensure that a binary tree can be serialized to a string and this string can be deserialized to the original tree structure.

Clarification: The input/output format is the same as how LeetCode serializes a binary tree. You do not necessarily need to follow this format, so please be creative and come up with different approaches yourself.

Example 1:

Input: root = [1,2,3,null,null,4,5]
Output: [1,2,3,null,null,4,5]


Example 2:

Input: root = []
Output: []


Constraints:

• The number of nodes in the tree is in the range [0, 104].
• -1000 <= Node.val <= 1000

# Algorithm

Pre-order traversal method.

For serialization, we start from the root node. If the node exists, store the value in the output string stream, and then recursively call the serialization function on its left and right child nodes.

For deserialization, we first read in the first character to generate a root node, and then recursively call the deserialization function on the left and right child nodes of the root node.

# Code

• import java.util.Arrays;
import java.util.Queue;

public class Serialize_and_Deserialize_Binary_Tree {

public static void main(String[] args) {
Serialize_and_Deserialize_Binary_Tree out = new Serialize_and_Deserialize_Binary_Tree();
Codec_bfs s = out.new Codec_bfs();

TreeNode root = new TreeNode(1);
root.left = new TreeNode(2);
root.right = new TreeNode(3);
root.right.left = new TreeNode(4);
root.right.right = new TreeNode(5);

//        System.out.println(s.serialize(root)); // 1,2,X,X,3,4,X,X,5,X,X,
//
//        System.out.println(s.deserialize("1,2,X,X,3,4,X,X,5,X,X,").val);

System.out.println(s.serialize(root)); // 1,2,3,X,X,4,5,X,X,X,X,

System.out.println(s.deserialize("1,2,3,X,X,4,5,X,X,X,X,").val);
}

// dfs
public class Codec {
private static final String spliter = ",";
private static final String nullNode = "X";

// Encodes a tree to a single string.
public String serialize(TreeNode root) {
StringBuilder sb = new StringBuilder();
buildString(root, sb);
return sb.toString();
}

// pre-order traversal
private void buildString(TreeNode node, StringBuilder sb) {
if (node == null) {
sb.append(nullNode).append(spliter);
} else {
sb.append(node.val).append(spliter);
buildString(node.left, sb);
buildString(node.right, sb);
}
}

// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
return buildTree(nodesList);
}

String val = nodes.removeFirst();
if (val.equals(nullNode)) {
return null;
} else {
TreeNode node = new TreeNode(Integer.parseInt(val));
node.left = buildTree(nodes);
node.right = buildTree(nodes);

return node;
}
}
}

/*
1
/ \
2   3
/ \
4   5

as "[1,2,3,null,null,4,5]"

for each parent with index-i, its children index:
left: 2*i+1
right: 2*i+2
*/
public class Codec_bfs {

private static final String spliter = ",";
private static final String nullNode = "X";

// Encodes a tree to a single string.
public String serialize(TreeNode root) {

if(root == null) {
return "";
}

StringBuilder result = new StringBuilder();

q.offer(root);
while(!q.isEmpty()) {
TreeNode current = q.poll();
if (current != null) {
result.append(current.val).append(spliter);
q.offer(current.left);
q.offer(current.right);
} else {
result.append(nullNode).append(spliter);
}
}

return result.toString();
}

// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {

String[] nodes = data.split(spliter);

TreeNode root = null;

for (int i = 0; 2 * i + 2 < nodes.length; i++) {

if (nodes[i].equals(nullNode)) {
continue;
}

TreeNode current = new TreeNode(Integer.parseInt(nodes[i]));

if (!nodes[2 * i + 1].equals(nullNode)) {
current.left = new TreeNode(Integer.parseInt(nodes[2 * i + 1]));
}

if (2*i+2 < nodes.length && !nodes[2 * i + 2].equals(nullNode)) {
current.right = new TreeNode(Integer.parseInt(nodes[2 * i + 2]));
}

if (i == 0) {
root = current;
}

}
return root;
}
}

}

############

/**
* Definition for a binary tree node.
* public class TreeNode {
*     int val;
*     TreeNode left;
*     TreeNode right;
*     TreeNode(int x) { val = x; }
* }
*/
public class Codec {
private static final String NULL = "#";
private static final String SEP = ",";

// Encodes a tree to a single string.
public String serialize(TreeNode root) {
if (root == null) {
return "";
}
StringBuilder sb = new StringBuilder();
preorder(root, sb);
return sb.toString();
}

private void preorder(TreeNode root, StringBuilder sb) {
if (root == null) {
sb.append(NULL + SEP);
return;
}
sb.append(root.val + SEP);
preorder(root.left, sb);
preorder(root.right, sb);
}

// Decodes your encoded data to tree.
public TreeNode deserialize(String data) {
if (data == null || "".equals(data)) {
return null;
}
for (String x : data.split(SEP)) {
}
return deserialize(vals);
}

private TreeNode deserialize(List<String> vals) {
String first = vals.remove(0);
if (NULL.equals(first)) {
return null;
}
TreeNode root = new TreeNode(Integer.parseInt(first));
root.left = deserialize(vals);
root.right = deserialize(vals);
return root;
}
}

// Your Codec object will be instantiated and called as such:
// Codec ser = new Codec();
// Codec deser = new Codec();
// TreeNode ans = deser.deserialize(ser.serialize(root));

• // OJ: https://leetcode.com/problems/serialize-and-deserialize-binary-tree/
class Codec {
private:
TreeNode *getNode(vector<string> &v, int &i) {
string s = v[i++];
return s == "#" ? NULL : new TreeNode(stoi(s));
}
public:
string serialize(TreeNode* root) {
if (!root) return "";
queue<TreeNode*> q;
q.push(root);
string ans;
while (!q.empty()) {
root = q.front();
q.pop();
if (!ans.empty()) ans += ',';
if (root) {
ans += to_string(root->val);
q.push(root->left);
q.push(root->right);
} else ans += '#';
}
return ans;
}
TreeNode* deserialize(string data) {
if (data.empty()) return NULL;
stringstream ss(data);
string val;
vector<string> v;
while (getline(ss, val, ',')) v.push_back(val);
TreeNode *root = new TreeNode(stoi(v[0]));
queue<TreeNode*> q;
q.push(root);
int i = 1;
while (i < v.size()) {
TreeNode *node = q.front();
q.pop();
node->left = getNode(v, i);
node->right = getNode(v, i);
if (node->left) q.push(node->left);
if (node->right) q.push(node->right);
}
return root;
}
};

• # Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Codec:
def serialize(self, root):
"""Encodes a tree to a single string.

:type root: TreeNode
:rtype: str
"""

if root is None:
return ''
res = []

def preorder(root):
if root is None:
res.append("#,")
return
res.append(str(root.val) + ",")
preorder(root.left)
preorder(root.right)

preorder(root)
return ''.join(res)

def deserialize(self, data):
"""Decodes your encoded data to tree.

:type data: str
:rtype: TreeNode
"""
if not data:
return None
vals = data.split(',')

def inner():
first = vals.pop(0)
if first == '#':
return None
return TreeNode(int(first), inner(), inner()) # seems using a constructor __init__(val, left, right)

return inner()

# Your Codec object will be instantiated and called as such:
# ser = Codec()
# deser = Codec()
# ans = deser.deserialize(ser.serialize(root))

############

from collections import deque

# bfs, each level based
class Codec:
def serialize(self, root):
"""Encodes a tree to a single string.

:type root: TreeNode
:rtype: str
"""
ret = []
queue = deque([root])
while queue:
top = queue.popleft()
if not top:
ret.append("None")
continue
else:
ret.append(str(top.val))
queue.append(top.left)
queue.append(top.right)
return ",".join(ret)

def deserialize(self, data):
"""Decodes your encoded data to tree.

:type data: str
:rtype: TreeNode
"""
data = data.split(",")
if data[0] == "None":
return None
root = TreeNode(int(data[0]))
queue = deque([root])
i = 0
while queue and i < len(data):
top = queue.popleft()
i += 1
left = right = None
if i < len(data) and data[i] != "None":
left = TreeNode(int(data[i]))
queue.append(left)
i += 1
if i < len(data) and data[i] != "None":
right = TreeNode(int(data[i]))
queue.append(right)

top.left = left
top.right = right

return root

# Your Codec object will be instantiated and called as such:
# codec = Codec()
# codec.deserialize(codec.serialize(root))


• /**
* Definition for a binary tree node.
* class TreeNode {
*     val: number
*     left: TreeNode | null
*     right: TreeNode | null
*     constructor(val?: number, left?: TreeNode | null, right?: TreeNode | null) {
*         this.val = (val===undefined ? 0 : val)
*         this.left = (left===undefined ? null : left)
*         this.right = (right===undefined ? null : right)
*     }
* }
*/

/*
* Encodes a tree to a single string.
*/
function serialize(root: TreeNode | null): string {
if (root == null) {
return '#';
}
const { val, left, right } = root;
return ${val},${serialize(left)},\${serialize(right)};
}

/*
* Decodes your encoded data to tree.
*/
function deserialize(data: string): TreeNode | null {
const n = data.length;
if (n === 1) {
return null;
}
const vals = data.split(',').reverse();
const renew = () => {
const val = vals.pop();
if (val == null || val === '#') {
return null;
}
return new TreeNode(Number(val), renew(), renew());
};
return renew();
}

/**
* Your functions will be called as such:
* deserialize(serialize(root));
*/


• /**
* Definition for a binary tree node.
* function TreeNode(val) {
*     this.val = val;
*     this.left = this.right = null;
* }
*/

/**
* Encodes a tree to a single string.
*
* @param {TreeNode} root
* @return {string}
*/
var serialize = function (root) {
return rserialize(root, '');
};

/**
* Decodes your encoded data to tree.
*
* @param {string} data
* @return {TreeNode}
*/
var deserialize = function (data) {
const dataArray = data.split(',');
return rdeserialize(dataArray);
};

const rserialize = (root, str) => {
if (root === null) {
str += '#,';
} else {
str += root.val + '' + ',';
str = rserialize(root.left, str);
str = rserialize(root.right, str);
}
return str;
};

const rdeserialize = dataList => {
if (dataList[0] === '#') {
dataList.shift();
return null;
}

const root = new TreeNode(parseInt(dataList[0]));
dataList.shift();
root.left = rdeserialize(dataList);
root.right = rdeserialize(dataList);

return root;
};

/**
* Your functions will be called as such:
* deserialize(serialize(root));
*/


• // Definition for a binary tree node.
// #[derive(Debug, PartialEq, Eq)]
// pub struct TreeNode {
//   pub val: i32,
//   pub left: Option<Rc<RefCell<TreeNode>>>,
//   pub right: Option<Rc<RefCell<TreeNode>>>,
// }
//
// impl TreeNode {
//   #[inline]
//   pub fn new(val: i32) -> Self {
//     TreeNode {
//       val,
//       left: None,
//       right: None
//     }
//   }
// }
use std::rc::Rc;
use std::cell::RefCell;
struct Codec {

}

/**
* &self means the method takes an immutable reference.
* If you need a mutable reference, change it to &mut self instead.
*/
impl Codec {
fn new() -> Self {
Codec {}
}

fn serialize(&self, root: Option<Rc<RefCell<TreeNode>>>) -> String {
if root.is_none() {
return String::from("#");
}
let mut node = root.as_ref().unwrap().borrow_mut();
let left = node.left.take();
let right = node.right.take();
format!(
"{},{},{}",
self.serialize(right),
self.serialize(left),
node.val
)
}

fn deserialize(&self, data: String) -> Option<Rc<RefCell<TreeNode>>> {
if data.len() == 1 {
return None;
}
Self::renew(&mut data.split(",").collect())
}

fn renew(vals: &mut Vec<&str>) -> Option<Rc<RefCell<TreeNode>>> {
let val = vals.pop().unwrap_or("#");
if val == "#" {
return None;
}
Some(Rc::new(RefCell::new(TreeNode {
val: val.parse().unwrap(),
left: Self::renew(vals),
right: Self::renew(vals),
})))
}
}

/**
* Your Codec object will be instantiated and called as such:
* let obj = Codec::new();
* let data: String = obj.serialize(strs);
* let ans: Option<Rc<RefCell<TreeNode>>> = obj.deserialize(data);
*/