Microsoft Interview Question for Software Engineers


Team: Cloud services
Country: United States




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

TRIE?

- afrika November 10, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Can we use additional structures within the class?

- Fernando November 10, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

c++, implementation

struct Person {
    string name;
    string phoneNumber;
};

class PhoneBook {
private:
    vector<Person> book;
    map<string, int> names;
    map<string, int> phones;
    int readCount;
    mutex mtx;
public:
    PhoneBook(vector<Person> people) : readCount(0) {
        vector<Person>::iterator it;
        
        for (it = people.begin(); it != people.end(); it++) {
            if (names.find(it->name) != names.end()) continue;
            if (phones.find(it->phoneNumber) != phones.end()) continue;
            book.push_back(*it);
            names.insert(make_pair(it->name, book.size() - 1));
            phones.insert(make_pair(it->phoneNumber, book.size() - 1));
        }
    }
    Person LookupByName(string name) {
        map<string, int>::iterator it;
        Person p;
        
        mtx.lock();
        readCount++;
        mtx.unlock();
        
        it = names.find(name);
        if (it != names.end()) p = book[it->second];
        
        mtx.lock();
        readCount--;
        mtx.unlock();
        
        return p;
    }
    Person LookupByPhoneNumber(string phoneNumber) {
        map<string, int>::iterator it;
        Person p;
        
        mtx.lock();
        readCount++;
        mtx.unlock();
        
        it = phones.find(phoneNumber);
        if (it != phones.end()) p = book[it->second];
        
        mtx.lock();
        readCount--;
        mtx.unlock();
        
        return p;
    }
    void AddPerson(Person person) {
        while (true) {
            mtx.lock();
            if (readCount == 0) break;
            mtx.unlock();
        }
        
        if (names.find(person.name) == names.end() && phones.find(person.phoneNumber) == phones.end()) {
            book.push_back(person);
            names.insert(make_pair(person.name, book.size() - 1));
            phones.insert(make_pair(person.phoneNumber, book.size() - 1));
        }
        
        mtx.unlock();
    }
};

- kyduke November 10, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
1
of 1 vote

Could you explain the use of readCount here.
Also, multiple threads can read together, it is only when another person is to be added, that we need thread protection right ?

- Fubar November 16, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;

namespace PhoneBook {

    public struct Person {

        public Person( string name, string phoneNumber ) {
            Name = name;
            PhoneNumber = phoneNumber;
        }

        public string Name { get; }
        public string PhoneNumber { get; }
    }

    public class Phonebook {

        private readonly object _lock = new object();

        private readonly ConcurrentDictionary<string, Person> _indexByName;

        private readonly ConcurrentDictionary<string, Person> _indexByPhoneNumber;

        public Phonebook( IEnumerable<Person> people ) {
        
            _indexByName = new ConcurrentDictionary<string, Person>();
            _indexByPhoneNumber = new ConcurrentDictionary<string, Person>();

            foreach ( var p in people ) {
                _indexByName.AddOrUpdate( p.Name, p, (s, pers) => pers );
                _indexByPhoneNumber.AddOrUpdate( p.PhoneNumber, p, (s, pers) => pers );
            }
        }

        public Person? LookupByName( string name ) {

            Person pers;
            var res = _indexByName.TryGetValue( name, out pers );
            return res ? (Person?)pers : null;
        }

        public Person? LookupByPhoneNumber( string phoneNumber ) {

            Person pers;
            var res = _indexByPhoneNumber.TryGetValue( phoneNumber, out pers );
            return res ? (Person?)pers : null;
        }

        public void AddPerson( Person person ) {

            Monitor.Enter( _lock );

            var res1 = LookupByName( person.Name );
            var res2 = LookupByPhoneNumber( person.PhoneNumber );

            if ( res1 != null && res2 != null ) {
                Monitor.Exit( _lock );
                return;
            }

            Person p;

            if ( res1 != null ) {
                
                _indexByPhoneNumber.TryRemove( ((Person)res1).PhoneNumber, out p );
                _indexByPhoneNumber.TryAdd( person.PhoneNumber, person );
            }
            
            if ( res2 != null ) {

                _indexByName.TryRemove( ((Person)res2).Name, out p );
                _indexByName.TryAdd( person.Name, person );
            }

            _indexByName.AddOrUpdate( person.Name, person, (s, pers) => person );
            _indexByPhoneNumber.AddOrUpdate( person.PhoneNumber, person, (s, pers) => person );

            Monitor.Exit( _lock );
        }
    }

}

- c# implementation November 11, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

c# implementation

using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;

namespace PhoneBook {

    public struct Person {

        public Person( string name, string phoneNumber ) {
            Name = name;
            PhoneNumber = phoneNumber;
        }

        public string Name { get; }
        public string PhoneNumber { get; }
    }

    public class Phonebook {

        private readonly object _lock = new object();

        private readonly ConcurrentDictionary<string, Person> _indexByName;

        private readonly ConcurrentDictionary<string, Person> _indexByPhoneNumber;

        public Phonebook( IEnumerable<Person> people ) {
        
            _indexByName = new ConcurrentDictionary<string, Person>();
            _indexByPhoneNumber = new ConcurrentDictionary<string, Person>();

            foreach ( var p in people ) {
                _indexByName.AddOrUpdate( p.Name, p, (s, pers) => pers );
                _indexByPhoneNumber.AddOrUpdate( p.PhoneNumber, p, (s, pers) => pers );
            }
        }

        public Person? LookupByName( string name ) {

            Person pers;
            var res = _indexByName.TryGetValue( name, out pers );
            return res ? (Person?)pers : null;
        }

        public Person? LookupByPhoneNumber( string phoneNumber ) {

            Person pers;
            var res = _indexByPhoneNumber.TryGetValue( phoneNumber, out pers );
            return res ? (Person?)pers : null;
        }

        public void AddPerson( Person person ) {

            Monitor.Enter( _lock );

            var res1 = LookupByName( person.Name );
            var res2 = LookupByPhoneNumber( person.PhoneNumber );

            if ( res1 != null && res2 != null ) {
                Monitor.Exit( _lock );
                return;
            }

            Person p;

            if ( res1 != null ) {
                
                _indexByPhoneNumber.TryRemove( ((Person)res1).PhoneNumber, out p );
                _indexByPhoneNumber.TryAdd( person.PhoneNumber, person );
            }
            
            if ( res2 != null ) {

                _indexByName.TryRemove( ((Person)res2).Name, out p );
                _indexByName.TryAdd( person.Name, person );
            }

            _indexByName.AddOrUpdate( person.Name, person, (s, pers) => person );
            _indexByPhoneNumber.AddOrUpdate( person.PhoneNumber, person, (s, pers) => person );

            Monitor.Exit( _lock );
        }
    }

}

- zr.roman November 11, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Sorry, I posted it 2 times here.

- zr.roman November 11, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Hi roman
In AddPerson method, you used "TryRemove, TryAdd" then AddOrUpdate.
It seems like duplicate for me. why did you use remove/add & addorupdate at the same time?

- ante5273 December 08, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

hello, ante5273,
that's because I maintain 2 indexes simultaneously: _indexByName and _indexByPhoneNumber. This causes implemented specific logic.
More detailed description I provided below in a comment to Surya's note. Please see there, so that I do not copy paste it from there to here.

- zr.roman December 08, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

package com.careercup.phonebook;

public class MainEx {
	public static void main(String[] args) {
		Person person1 = new Person("jmk", "8743562734");
		Person person2 = new Person("emmt", "3332322343");
		Person person3 = new Person("eclipse", "654345678");
		Phonebook pb = new Phonebook();
		pb.addPerson(person1, person2, person3);

		System.out.println(pb.lookUpByName("jmk"));

	}

}

package com.careercup.phonebook;

import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

public class Phonebook {

	private ConcurrentHashMap<String, Person> _db = new ConcurrentHashMap<String, Person>();

	public Phonebook() {

	}

	public Person lookUpByName(String name) {
		for (Entry<String, Person> e : _db.entrySet()) {
			if (e.getValue().getName().equals(name)) {
				return e.getValue();
			}
		}
		return null;
	}

	public Person lookUpByPhoneNumber(String phoneNumber) {
		return _db.get(phoneNumber);
	}

	public synchronized void addPerson(Person person) {
		_db.put(person.getPhoneNumber(), person);
	}

	public synchronized void addPerson(Person... persons) {
		for (Person person : persons) {
			_db.put(person.getPhoneNumber(), person);
		}
	}
}


package com.careercup.phonebook;

public class Person {
	private String name;
	private String phoneNumber;

	public Person() {
		super();
	}

	public Person(String name, String phoneNumber) {
		super();
		this.name = name;
		this.phoneNumber = phoneNumber;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getPhoneNumber() {
		return phoneNumber;
	}

	public void setPhoneNumber(String phoneNumber) {
		this.phoneNumber = phoneNumber;
	}

	@Override
	public String toString() {
		return "Person [name=" + name + ", phoneNumber=" + phoneNumber + "]";
	}

}

- Unknown November 12, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Thanks for the responses. @zr.roman, I was wondering why you added TryRemove and TryAdd statements with If conditions. Because, the AddOrUpdate statements at the end will do the required updates. why we need to remove and add the items explicitly if we doing AddOrUpdate?

- Surya November 12, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Yes, good question, and frankly, my first version was exactly as you described in your question: the method "AddPerson" contained only 2 method calls - _indexByName.AddOrUpdate and _indexByPhoneNumber.AddOrUpdate.
But - tests failed!
The reason is the following:
imagine, the phone book contains the entry "Tom, 123-456-789", and you try to insert entry "Tom, (+1)123-456-789", i.e. the update of the existing record (phone number should be updated).
The method _indexByName.AddOrUpdate works OK: it detects that the key "Tom" already exists in _indexByName, and it overwrites the whole record.
But method _indexByPhoneNumber.AddOrUpdate is a problem. Because before calling this method, _indexByPhoneNumber contains record "123-456-789, {Tom}" and when you put "(+1)123-456-789, {Tom}" into method, it detects that there is no key "(+1)123-456-789" and creates a new entry "(+1)123-456-789, {Tom}", so _indexByPhoneNumber will contain two entries:
"(+1)123-456-789, {Tom}"
and
"123-456-789, {Tom}",
and it is incorrect, because we intended to update the record, not to insert another one. So, I explicitly remove the old record and insert the new one, which is actually the update of the removed record.
The same (mirror situation) is with _indexByName, when you try to update the name of a person, while the phone number is not changed (I assume that there are no 2 or more persons with the same phone number, and it makes sense).
So, I added TryRemove and TryAdd statements with If conditions.

- zr.roman November 12, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

struct Person
{
string name;
string phno;
Person()
{

}
Person(string x, string y)
{
name=x;
phno=y;
}
};
class PhoneBook
{
std::map<std::string, std::string> phoneBook;
public:
PhoneBook(std::vector<struct Person>& p)
{
for(size_t i=0; i<p.size(); i++)
{
phoneBook.insert(std::pair<string,string>(p[i].name, p[i].phno));
}
}

Person LookUpByName(string name)
{
map<string,string>::iterator it;
Person p;
it = phoneBook.find(name);
if(it != phoneBook.end())
{
p.name = it->first;
p.phno = it->second;
}
return p;

}

Person LookUpByPhNo(string phno)
{
map<string,string>::iterator it;
Person p;
for(it= phoneBook.begin(); it!= phoneBook.end(); ++it)
{
if(it->second == phno)
{
p.name = it->first;
p.phno= it->second;

}
}

return p;
}

void AddPerson(Person p)
{
map<string,string>::iterator it;
std::lock_guard<std::mutex> locker(mu);
it= phoneBook.find(p.name); //Case of updation
if(it != phoneBook.end())
it->second = p.phno;

phoneBook.insert(std::pair<string,string>(p.name, p.phno));
}

};

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

struct Person
{
string name;
string phno;
Person()
{

}
Person(string x, string y)
{
name=x;
phno=y;
}
};
class PhoneBook
{
std::map<std::string, std::string> phoneBook;
public:
PhoneBook(std::vector<struct Person>& p)
{
for(size_t i=0; i<p.size(); i++)
{
phoneBook.insert(std::pair<string,string>(p[i].name, p[i].phno));
}
}

Person LookUpByName(string name)
{
map<string,string>::iterator it;
Person p;
it = phoneBook.find(name);
if(it != phoneBook.end())
{
p.name = it->first;
p.phno = it->second;
}
return p;

}

Person LookUpByPhNo(string phno)
{
map<string,string>::iterator it;
Person p;
for(it= phoneBook.begin(); it!= phoneBook.end(); ++it)
{
if(it->second == phno)
{
p.name = it->first;
p.phno= it->second;

}
}

return p;
}

void AddPerson(Person p)
{
map<string,string>::iterator it;
std::lock_guard<std::mutex> locker(mu);
it= phoneBook.find(p.name); //Case of updation
if(it != phoneBook.end())
it->second = p.phno;

phoneBook.insert(std::pair<string,string>(p.name, p.phno));
}

};

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

class PhoneBook
{
	shared_timed_mutex write;
	typedef unordered_map<string, std::shared_ptr<Person>> PersonMap;
	PersonMap  _map;
public:
	PhoneBook()
	{

	}
	void addPerson(const Person & p)
	{
		lock_guard<shared_timed_mutex> w(write);
		shared_ptr<Person> s (new Person(p));
		_map[p.name] = s;
		_map[p.phone] = s;
	
	}
	string lookupByPhone(string phone)
	{
		return lookup(phone).name;
	}
	string lookupByName(string name)
	{
		return lookup(name).phone;
	}
private:
	Person lookup(string key)
	{
		shared_lock<shared_timed_mutex> r(write);
		PersonMap::iterator i = _map.find( key );
		
		if (_map.end() == i) {
			Person pp;
			return pp;
		}
		return *(*i).second.get();
	}

};

- drolmal March 30, 2017 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 1 vote

import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class Person{
	String phoneNumber;
	String personName;
	public Person(String phoneNumber, String personName) {
		super();
		this.phoneNumber = phoneNumber;
		this.personName = personName;
	}
	@Override
	public String toString() {
		return "Person [phoneNumber=" + phoneNumber + ", personName=" + personName + "]";
	}
	public String getPhoneNumber() {
		return phoneNumber;
	}
	public void setPhoneNumber(String phoneNumber) {
		this.phoneNumber = phoneNumber;
	}
	public String getPersonName() {
		return personName;
	}
	public void setPersonName(String personName) {
		this.personName = personName;
	}
	
}
public class PhoneBook {
	
	private ConcurrentHashMap<String, Person> phoneNumberMap;
	private ConcurrentHashMap<String, Person> personNameMap;
	private Lock l ;
	public PhoneBook(List<Person> person){
		phoneNumberMap = new ConcurrentHashMap<String, Person>();
		personNameMap = new ConcurrentHashMap<String, Person>();
		l = new ReentrantLock();
		for(Person p: person){
			AddPerson(p);
		}
	}
	
	public void AddPerson(Person p){
		if(phoneNumberMap.containsKey(p.getPhoneNumber()) && personNameMap.containsKey(p.getPersonName())){
			//already presnt
			return ;
		}
		try{
			l.lock();
			if(phoneNumberMap.containsKey(p.getPhoneNumber())){
				Person oldPerson = phoneNumberMap.get(p.getPhoneNumber());
				phoneNumberMap.put(p.getPhoneNumber(), p);
				personNameMap.remove(oldPerson.getPersonName());
				personNameMap.put(oldPerson.getPersonName(), p);
			}
			else if(personNameMap.containsKey(p.getPhoneNumber())){
				Person oldPerson = personNameMap.get(p.getPhoneNumber());
				personNameMap.put(p.getPhoneNumber(), p);
				phoneNumberMap.remove(oldPerson.getPersonName());
				phoneNumberMap.put(oldPerson.getPersonName(), p);
			} else{
				personNameMap.put(p.getPersonName(), p);
				phoneNumberMap.put(p.getPhoneNumber(), p);
			}
		}finally{
			l.unlock();
		}
	}
	
	public Person lookupByName(String name){
		return personNameMap.get(name);
	}
	public Person lookupByPhonenumber(String phoneNumber){
		return phoneNumberMap.get(phoneNumber);
	}
	

}

- Anonymous November 18, 2015 | Flag Reply


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