Microsoft Interview Question
Software Engineer / DevelopersCountry: United States
Guys, why do you think this solution is very nice? Here is infinite recursion call in root.appendChild(deserialize(s)); and infinite loop in while() because s is not modified and deserialize() itself does not depend on position in a string and does not return any position and pos is not changed in while() loop. The "nice" here only the idea of using recursion, but implementation is wrong.
Create a stack. Whenever a character is encountered which is followed by '<', create a new node as a child of the topmost element in the stack and insert the new node on the stack.
Pop out the topmost node from the stack each time '>' is encountered.
I assume that e is child of b and f is child of d.
If e is child of both b and a, then instead of stack, we can use array.
C code, but assumes that there can be atmax 3 children of a node -
typedef struct node {
char data;
struct node **list;
}node;
node ** deserialize_tree(char * str, int *j){
if(str[*j] != '\0'){
if(str[*j] == '<' ){
(*j)++;
struct node **arr = (struct node **)malloc(sizeof(struct node *)*3);
int i = 0;
while(str[*j] != '>'){
struct node * temp = (struct node *)malloc(sizeof(struct node ));
temp->data = str[*j];
(*j)++;
temp->list = deserialize_tree(str, j);
arr[i] = temp;
i++;
}
(*j)++;
return arr;
}
}
return null;
}
void print_ntree(node * temp){
if(temp){
printf("%c ", temp->data);
printf("children ");
node **list = temp->list;
int i =0;
while(list && i < 3){
print_ntree(list[i]);
i++;
}
printf("\n");
}
}
void deserialize_tree_util(){
char * str = "a<b<e<>>c<>d<f<>>>";
struct node * temp = (struct node *)malloc(sizeof(struct node ));
temp->data = str[0];
int j = 1;
temp->list = deserialize_tree(str, &j);
print_ntree(temp);
}
Please read like this. apologies for this ugly formatting by me. I could not properly structure it.
A(Root)
B(A's child) C (A's child) D(A's child)
E(A & B's child) F (A & D's child)
Did not test.
Node *deserialize(std::string& s) {
std::map<char, Node*> hash;
std:stack<char> stack;
std:vector<char> temp;
int ptr = 0;
while(ptr < s.length()) {
stack.push(s[ptr]);
if(stack.peek() == '>') {
stack.pop(); // pop '>'
while(stack.peek() != '<') {
temp.push_back(stack.pop());
}
stack.pop(); // pop '<'
if(hash[stack.peek()] == NULL) { // check parent
hash[stack.peek()] = new Node(stack.peek()); // create parent node
}
for(var it = stack.begin(); it != stack.end(); ++ it) {
hash[stack.peek()]->child.push_back(*it);
}
}
}
return stack.pop();
}
package mirco;
import java.util.ArrayList;
import java.util.List;
public class ParseStringToTree {
static String input = "a<b<e<>>c<>d<f<>>>";
public static void main(String[] args) {
TreeNode head = null;
TreeNode current = null;
TreeNode parent = null;
for (Character c : input.toCharArray()) {
switch (c) {
case '<':
parent = current;
break;
case '>':
current = current.parent;
break;
default:
TreeNode child = new TreeNode(c, new ArrayList<TreeNode>());
child.parent = current;
if(null!=current){
current.nexts.add(child);
} else{
head = child;
}
current = child;
}
}
System.out.println("head = " + head);
}
static class TreeNode {
public char value;
public List<TreeNode> nexts;
public TreeNode parent;
TreeNode(char value, List<TreeNode> nexts) {
this.value = value;
this.nexts = nexts;
}
}
}
Here is my solution in JAVA. It's tested.
----------InputString.java----------
package TreeTest;
public class InputString
{
public char[] inputStringArray;
public int index = 0;
public InputString(String str)
{
inputStringArray = str.toCharArray();
}
public char next()
{
char tmp = 0;
if (index < inputStringArray.length)
{
tmp = inputStringArray[index];
index++;
}
return tmp;
}
public String toString()
{
String result = "";
if(inputStringArray.length>0)
{
for(int i=0; i<inputStringArray.length; i++)
{
result += String.valueOf(inputStringArray[i]);
}
}
return result;
}
}
----------Link.java----------
package TreeTest;
public class Link<T>
{
public T element;
public Link<T> child;
public Link<T> sibling;
public Link(T data)
{
this.element = data;
child = null;
sibling = null;
}
public Link<T> addChild(T data)
{
Link<T> newnode = new Link<T>(data);
child = newnode;
return newnode;
}
public Link<T> addSibling(T data)
{
Link<T> newnode = new Link<T>(data);
sibling = newnode;
return newnode;
}
}
----------Tree.java----------
package TreeTest;
public class Tree<T>
{
public Link<T> root;
public int num;//how many nodes
public Tree()
{
root = null;
num = 0;
}
public Link<T> addChild(Link<T> parentLink, T newValue)
{
num++;
if (null == parentLink)
{
root = new Link<T>(newValue);
return root;
}
else
{
return parentLink.addChild(newValue);
}
}
public Link<T> addSibling(Link<T> currentLink, T newValue)
{
num++;
return currentLink.addSibling(newValue);
}
public void serialize()
{
if (null == root)
{
System.out.println("No tree can be serialized.");
return;
}
else
{
preorderViewTree(root);
}
}
public void preorderViewTree(Link<T> node)
{
if ( null == node )
{
return;
}
else
{
System.out.print(node.element + "<");
if(null != node.child)
{
preorderViewTree(node.child);
}
System.out.print(">");
preorderViewTree(node.sibling);
}
}
public void deSerialize(String str)
{
if( null == str || "" == str)
System.out.println("Please input a tree string.");
else
{
InputString inStr = new InputString(str.replace("<",""));// "<" is useless for creating a tree.
//1: add sibling 2: add child
preorderCreateTree(root, 2, inStr);
}
}
public void preorderCreateTree(Link<T> pnode, int relation, InputString inputStr)
{
char currentStr = inputStr.next();
if ( currentStr == 0)
return;
/* for debug-------------------------------------
System.out.print("CurrentChar: "+ currentStr +" Tree:");
this.serialize();
System.out.println("");
----------------------------------------------*/
if('>' == currentStr)
{
return;
}
else
{
if(relation == 1)
pnode = this.addSibling(pnode,(T)String.valueOf(currentStr));
else
pnode = this.addChild(pnode, (T)String.valueOf(currentStr));
preorderCreateTree(pnode, 2, inputStr);//child
preorderCreateTree(pnode, 1, inputStr);//sibling
}
}
}
----------HandleTree.java----------
package TreeTest;
public class HandleTree
{
public static void main(String argus[])
{
Tree<String> tree = new Tree<String>();
/*
tree.addChild(tree.addChild(tree.addChild(null, "A"), "B"), "E");
tree.addChild(tree.addSibling(tree.addSibling(tree.root.child, "C"), "D"), "F");
tree.serialize();
System.out.println("");
*/
tree.deSerialize("A<B<E<>>C<>D<F<>>>");
tree.serialize();
System.out.println("");
System.out.println("How many nodes:" + tree.num);
}
}
- taylorz September 11, 2013