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.
Java Solution 1 – Level Order Traveral
// Encodes a tree to a single string. public String serialize(TreeNode root) { ArrayList<String> list = new ArrayList<>(); LinkedList<TreeNode> q = new LinkedList<>(); q.offer(root); while (!q.isEmpty()) { TreeNode h = q.poll(); if (h == null) { list.add("#"); } else { list.add("" + h.val); q.offer(h.left); q.offer(h.right); } } return String.join(",", list); } // Decodes your encoded data to tree. public TreeNode deserialize(String data) { String[] arr = data.split(","); if (arr[0].equals("#")) { return null; } TreeNode root = new TreeNode(Integer.parseInt(arr[0])); LinkedList<TreeNode> q = new LinkedList<>(); q.offer(root); int i = 1; while (!q.isEmpty()) { TreeNode h = q.poll(); if (h != null) { TreeNode left = null; if (!arr[i].equals("#")) { left = new TreeNode(Integer.parseInt(arr[i])); } h.left = left; q.offer(left); i++; TreeNode right = null; if (!arr[i].equals("#")) { right = new TreeNode(Integer.parseInt(arr[i])); } h.right = right; q.offer(right); i++; } } return root; } |
Java Solution 2 – Preorder Traversal
// Encodes a tree to a single string. public String serialize(TreeNode root) { if(root==null) return null; Stack<TreeNode> stack = new Stack<TreeNode>(); stack.push(root); StringBuilder sb = new StringBuilder(); while(!stack.isEmpty()){ TreeNode h = stack.pop(); if(h!=null){ sb.append(h.val+","); stack.push(h.right); stack.push(h.left); }else{ sb.append("#,"); } } return sb.toString().substring(0, sb.length()-1); } // Decodes your encoded data to tree. public TreeNode deserialize(String data) { if(data == null) return null; int[] t = {0}; String[] arr = data.split(","); return helper(arr, t); } public TreeNode helper(String[] arr, int[] t){ if(arr[t[0]].equals("#")){ return null; } TreeNode root = new TreeNode(Integer.parseInt(arr[t[0]])); t[0]=t[0]+1; root.left = helper(arr, t); t[0]=t[0]+1; root.right = helper(arr, t); return root; } |
hahhhhahaha
When you have String[] then you don’t need another queue…
…
int n = str.length;
// change # to null
for (int idx = 0; idx = 0; –idx) {
if (null == str[idx])
continue;
Node cur = new Node(str[idx]);
int left = 2 * idx + 1;
int right = left + 1;
if (left < n) {
cur.left = new Node(str[left]);
}
if (right < n) {
cur.right = new Node(str[right]);
}
}
function Node(val, left, right) {
this.val = val;
this.left = left;
this.right = right;
}
var child1 = new Node(1, new Node(4), new Node(10))
var root = new Node(1, child1, new Node(22, new Node(3)));
function parseTree(node, arr) {
var value = node ? node.val : ‘#’;
arr.push(value);
if (node) {
parseTree(node.left, arr);
parseTree(node.right, arr);
}
}
const arr = [];
parseTree(root, arr);
console.log(arr);
root = new Node(arr[0]);
let i = 1;
let node = root;
while (i < arr.length) {
const val = arr[i];
if (val !== '#') {
const child = new Node(val);
child.parent= node;
node[ typeof(node.left) === 'undefined' ? 'left' : 'right'] = child;
node = child;
}else{
// '#' encountered;
node[typeof(node.left) === 'undefined' ? 'left' : 'right'] = null;
while(node && typeof(node.left) !== 'undefined' && typeof(node.right) !== 'undefined'){
node = node.parent;
}
}
i++;
}
debugger
console.log(root);
why have we used an array t of size 1 and increading the value of 0th index, instead of just using a variable and incrementing it..
In the while loop, can we remove queue.offer(null) when string in the arr is “#”? so it doesn’t need to check t=null when we poll element from queue. Is there any reason to add null into the queue?
while(!queue.isEmpty()){
TreeNode t = queue.poll();
if(!arr[i].equals("#")){
t.left = new TreeNode(Integer.parseInt(arr[i]));
queue.offer(t.left);
}else{
t.left = null;
}
i++;
if(!arr[i].equals("#")){
t.right = new TreeNode(Integer.parseInt(arr[i]));
queue.offer(t.right);
}else{
t.right = null;
}
i++;
}
t is an array with one element. When the recursion function changed the t inside. The t outside will be modified at the same time. Since they share the same memory space. In another word, the reference t inside is different from the reference t outside, but they point to the same memory space.
I’m confused as to why the second solution works, since java is passed by value how would the T get updated?