Microsoft Interview Question for Software Engineer / Developers


Team: Cloud
Country: United States
Interview Type: In-Person




Comment hidden because of low score. Click to expand.
0
of 0 vote

To add the random requirement each time you create a copy node, add it to a hashmap.
After the copy ends start from the root of the copy, and assign each node a random node from the hashmap.

- the one September 12, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

If extra memory is allowed then the hash table will work

1. Create a copy of an original list setting up only prev and next pointers
	2. While doing #1 create a map keyed on nodes in original list and valued on corresponding nodes in cloned list
	3. Iterate through both lists at the same time and set:
		NodeInClonedList.random = map[NodeInOriginalList.random]

Without extra memory you have to modify the original list so the "prev" pointer would point to a cloned node.

- trickster October 08, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

My understanding is that you need to create exact copy of initial list - so at the end you'll have 2 separate lists - given and its copy. I used hash table which as key stores node from the initial list and as a value - corresponding node from the copy list. C# solution:

class DoubleLinkListNode<T>
    {
        public DoubleLinkListNode<T> Next { get; set; }
        public DoubleLinkListNode<T> Prev { get; set; }
        public DoubleLinkListNode<T> Random { get; set; }
        public T Data { get; set; }

        public DoubleLinkListNode(T data)
        {
            Next = Prev = Random = null;
            Data = data;
        }

        public DoubleLinkListNode(T data, DoubleLinkListNode<T> randomNode)
        {
            Next = Prev = null;
            Random = randomNode;
            Data = data;
        }
    }

    class DoubleLinkList<T>
    {
        public DoubleLinkListNode<T> Head { get; set; }
        public DoubleLinkListNode<T> Tail { get; set; }

        public DoubleLinkList()
        {
            Head = Tail = null;
        }

        public void AddItem(T data, DoubleLinkListNode<T> randomNode)
        {
            DoubleLinkListNode<T> newNode = new DoubleLinkListNode<T>(data, randomNode);
            if (Tail == null)
            {
                Head = Tail = newNode;
            }
            else
            {
                Tail.Next = newNode;
                newNode.Prev = Tail;
                Tail = newNode;
            }
        }

        public DoubleLinkList<T> Copy()
        {
            DoubleLinkList<T> listCopy = null;
            Hashtable hashTable = null;
            DoubleLinkListNode<T> current = null;
            DoubleLinkListNode<T> listCopyNode = null;

            if (Head != null)
            {
                hashTable = new Hashtable();
                listCopy = new DoubleLinkList<T>();
                current = Head;
                while (current != null)
                {
                    if (hashTable.Contains(current) == false)
                    {
                        listCopy.AddItem(current.Data, null);
                        hashTable.Add(current, listCopy.Tail);
                    }
                    else
                    {
                        listCopyNode = (DoubleLinkListNode<T>)hashTable[current];
                        listCopy.Tail.Next = listCopyNode;
                        listCopyNode.Prev = listCopy.Tail;
                        listCopy.Tail = listCopy.Tail.Next;
                    }

                    if (current.Random != null)
                    {
                        if (hashTable.Contains(current.Random) == false)
                        {
                            listCopyNode = new DoubleLinkListNode<T>(current.Random.Data);
                            hashTable.Add(current.Random, listCopyNode);
                        }
                        else
                        {
                            listCopyNode = (DoubleLinkListNode<T>)hashTable[current.Random];
                        }
                        listCopy.Tail.Random = listCopyNode;
                    }

                    current = current.Next;
                }
            }

            return listCopy;
        }

        public void PrintListForward()
        {
            DoubleLinkListNode<T> current = null;

            if (Head != null)
            {
                current = Head;
                while (current != null)
                {
                    Console.WriteLine("Node data: {0}, random node data: {1}", 
                                      current.Data,
                                      (current.Random == null) ? "null" : current.Random.Data.ToString());
                    current = current.Next;
                }
            }
        }

        public void PrintListBackward()
        {
            DoubleLinkListNode<T> current = null;

            if (Tail != null)
            {
                current = Tail;
                while (current != null)
                {
                    Console.WriteLine("Node data: {0}, random node data: {1}",
                                      current.Data,
                                      (current.Random == null) ? "null" : current.Random.Data.ToString());
                    current = current.Prev;
                }
            }
        }
    }

- AK October 27, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

There is a neat trick to do this in constant space without modifying the input linked list.
It will require two passes however.

Pass 1:
-Create copy of each node. Set previous & next correctly in the new node
-To keep track of new node reference, use random reference of original node. However before you overwrite random reference of the original node, preserve it in the random reference of the new node, i.e.:

Node newNode = new Node(oldNode.value);
    newNode.previous = last; last.next = newNode;
    newNode.random = oldNode.random; //Preserving old node's random reference in the newly created node's random pointer
    oldNode.random = newNode; //Keeping the new reference in the random reference of old Node
    last = newNode;

Pass 2:
-Iterate over both lists together.
-For each node, restore the random reference in the original list. However before overwriting that, use the random reference of the newNode to retrieve corresponding random reference for the new node. i.e.:

Node oldRandom = newNode.random;
    newNode.random = oldRandom.random; //oldRandom's random reference is pointing to the corresponding new node
    oldNode.random = oldRandom; //restore the random reference of the old node so that input list is not modified

- Bhaddu November 07, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

a solution in C++

typedef struct node {
    node* next;
    node* prev;
    node* rand;
}

void copyLinkedList (node* src , node* dst) {
    node* currS = src;
    node* currD = dst;
    node* prevD = NULL;
    while (currS) {
        currD          = new node;
        currD->prev    = prevD;
        currD->rand    = currS->rand;
        currS->prev    = currD;
        if (prevD) {
            prevD->next = currD;
        }
        
        prevD        = currD;
        currS        = currS->next;
    }
    
    //change rand pointer in dst
    currD = dst;
    while(currD) {
        currD->rand = currD->rand->prev;
    }
    
    //return prev pointer in src
    currS = src;
    prevD = NULL;
    while (currS) {
        currS->prev  = prevD;
        prevD        = currS;
        currS        = currS->next;
    }

}

- shanik December 16, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Node* clone(Node* head)
{
    if(head == NULL)
        return NULL;
    Node* temp =head;
    Node* sectemp = head;
    Node* clonehead = NULL;
    bool first =false;
    while(head)
    {
        Node* clone = new Node();
        if(head->prev == NULL) //it means the first node
        {
            clone->prev =NULL;
            head->prev = clone; //change original->prv to the current clone node (basically, we assign a clone node for the current node, instead of using a hashtable)
        }
        else
        {
            //until now head->prev is still pointing to its previous node but after setting clone->prev we need to change it.head->prev->prev points to the previous node in cloned list
            clone->prev = head->prev->prev;
            clone->prev->next = clone;
            head->prev = clone;
        }
        //to keep the head of the cloned list for second pass
        if(!first)
        {
            clonehead = clone;
            first = true;
        }
        head = head->next;
    }
    Node* res = clonehead;
    
    //set the cloned list random pointer
    while(clonehead)
    {
        clonehead->random = temp->random->prev;
        clonehead = clonehead->next;
        temp=temp->next;
    }
    
    //now fix the original list's prev pointer
    first =false;
    Node* lastnode =NULL;
    while(sectemp)
    {
      if(!first)
      {
          sectemp->prev= NULL;
          first =true;
          lastnode = sectemp;
      }
      else
      {
          sectemp->prev = lastnode;
          lastnode=sectemp;
      }
        sectemp =sectemp->next;
    }
    
    return res;
   }

- This code can solve the problem with O(N) time and constant memory. February 14, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

What do you think about that?

Node * clone, * prev;
if (head -> prev == null) {
	clone = new Node();
	clone -> prev = Null;
	prev = clone;
	head = head ->next;
}

While (head != Null) {
	Node * clone = new Node();
	clone -> prev = prev;
	prev->next = clone;
	prev = clone;
	head = head-> next;
}
prev -> next = Null;

- Fahmy April 14, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Here is the algorithm for this
We need to do two pass to the list, in one pass, we will create the new list, set its next and previous pointers, in the next run, we will set the random pointers

CloneList(List P)
	List N = New Empty List;
	// Node1 and Node2 are there is keep track of first node of each list.
	Node1 = P.FirstNode; 
	Node2 = N.FirstNode; // this will be null
	// This while loop will copy the old list to new list
	While Node1 is not null
		Create a new Node Node_New;
		if Node2 is null then
			Node2 = Node_New;Node2.Previous is Null;Node2.Next is null;
		else
			Node_New.Previous = Node2;
			Node_New.Next is null
			Node2.Next = New_New;
			Node2 = Node_New;
		Node2.Random = Node1.Random;
		Node1.Random = Node2;
		Node1 = Node1.Next;
	Node1 = P.FirstNode; 
	Node2 = N.FirstNode;
	// This while loop will set the random node to its correct value
	While Node1 is not null 
		Node2.Random = Node2.Random.Random
	Return List N;

Complexity
Time : O(N)
Space O(N) : Need to store the new list

- sonesh June 07, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
-2
of 2 vote

A Solution in Objective C:
PS:
Node/DLL Structure: ...Node <- prev.(Node).next -> Node...

- (Node *)copyDLL:(Node *)p {
	if (!p) {
		return nil;
	}
	
	Node *clone = new Node;
	clone.val = p.val;

	clone.next = [self copyDLLNext:p.next];
	if (clone.next) {
		clone.next.prev = clone;
	}

	clone.prev = [self copyDLLPrev:p.prev];
	if (clone.prev) {
		clone.prev.next = clone;
	}
	return clone;
}

- (Node *)copyDLLNext:(Node *)p {
	if (!p) {
		return nil;
	}

	Node *clone = new Node;
	clone.val = p.val;

	clone.next = [self copyDLLNext:p.next];
	if (clone.next) {
		clone.next.prev = clone;
	}
	return clone;
}

- (Node *)copyDLLPrev:(Node *)p {
	if (!p) {
		return nil;
	}

	Node *clone = new Node;
	clone.val = p.val;

	clone.prev = [self copyDLLPrev:p.prev];
	if (clone.prev) {
		clone.prev.next = clone;
	}
	return clone;
}

- etaCarinae September 02, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

It would be great if you can describe your algo or put some comments so others can read it quickly.

- Monkey_In_The_Middle September 05, 2014 | Flag


Add a Comment
Name:

Writing Code? Surround your code with {{{ and }}} to preserve whitespace.

Books

is a comprehensive book on getting a job at a top tech company, while focuses on dev interviews and does this for PMs.

Learn More

Videos

CareerCup's interview videos give you a real-life look at technical interviews. In these unscripted videos, watch how other candidates handle tough questions and how the interviewer thinks about their performance.

Learn More

Resume Review

Most engineers make critical mistakes on their resumes -- we can fix your resume with our custom resume review service. And, we use fellow engineers as our resume reviewers, so you can be sure that we "get" what you're saying.

Learn More

Mock Interviews

Our Mock Interviews will be conducted "in character" just like a real interview, and can focus on whatever topics you want. All our interviewers have worked for Microsoft, Google or Amazon, you know you'll get a true-to-life experience.

Learn More