Microsoft Interview Question for SDE-2s


Country: India




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

This can be done in linear time, with no extra space. We do a linear based insertion sort, but do it twice, once for 0, and once for 1. Here's the code

void sort (vector<int> nums) {
	//call linear insertion on 0 once, moves all 0's to the front
	int zEnd = move(nums, 0, 0);
	//call linear insertion on 1, moves all 1s after end of 0s. 2's are automatically sorted.

	int oEnd = move(nums, zEnd, 1);
}
//this is the linear insertion sort. it swaps each occurence of val with the moving pointer. 
int move(vector<int> nums, int start, int val) {
	int i = start;
	int j = start;
	while(true) {
		try {
			if(nums.at(j) == val)
				swap(nums, i++, j);
			j++;
		} catch(exception e) {
			break;
		}
	}
	return i;
}

- Ravish chawla October 18, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
1
of 1 vote

If you need speed over space, we can create an additional array to keep track each item in the input array and its corresponding count. So the first pass, we calculate the count of each input array item and the second pass we just update the original input array based on the content of additional array we got from the first pass:

class TestFun {
    class func sortZeroOneTwo(var input:[Int]) -> [Int] {
        
        var table = [Int](count: 3, repeatedValue: 0)
        
        for var i = 0; i < input.count; i++ {
            if table[input[i]] == 0 {
                table[input[i]] = 1
            } else {
                table[input[i]]++
            }
        }
        
        var index = 0
        for var i = 0; i < input.count; i++ {
            while index < table.count && table[index] <= 0 {
                index++
            }
            
            if index >= table.count {
                //nothing can be done here
                break
            }
            
            if table[index] > 0 {
                input[i] = index
                table[index]--
            }
        }
        
        return input
    }
}

- Willy Tan October 18, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
1
of 1 vote

Sorry I forget to mention

He has clearly mentioned that we should traverse the array once

- NoMind October 18, 2015 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

He is a solution. It keeps track of the end of the 0's and the start of the 2's.

public static void sortZeroOneTwoArray(int[] a) {
    if (a == null) {
        return;
    }
    int zeroEnd = -1, twoStart = -1;
    for (int i = 0; i < a.length; i++) {
        if(a[i] < 0 || a[i] > 2) {
            System.out.println("Array value out of bounds");
            return;
        }
        else if (a[i] == 2 && twoStart < 0) {
            twoStart = i;
        } else if (a[i] == 1 && twoStart > -1) {
            a[i] = 2;
            a[twoStart++] = 1;
        } else if (a[i] == 0) {
            if (twoStart > -1) {
                a[i] = 2;
                a[twoStart++] = a[++zeroEnd];
                a[zeroEnd] = 0;
            } else if (zeroEnd < i - 1) {
                a[++zeroEnd] = 0;
                a[i] = 1;
            } else {
                zeroEnd++;
            }
        }
    }
}

- amp October 18, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
1
of 3 vote

this is the dutch national flag problem. you have to be careful to only increment mid if you know it is a one.

public void sortFlag(int[] a){
	int start = 0;
	int mid = 0;
	int end = a.length;

	for (int i = 0; i < a.length; i++){
		if (mid == 0) {
			swap(start, mid);
			start++;
		}
		if (mid == 2) {
			swap(mid, end);
			end--;
		}

		if (mid == 1) mid++;

	}
}

- anon October 20, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
1
of 1 vote

Here is a solution satisfying your conditions
1. No array length (or size) use
2. Single parse
This is C#, this question seems to expect C++

public void Sort(int[] arr)
{
	try 
	{
		int i = 0;
		int firstOne = int.MaxValue, firstTwo = int.MaxValue;

		while (true)
		{
			switch (arr[i]) {
				case 0:
					if (i > firstOne)
					{
						Swap(arr, i, firstOne);
						firstOne++;
					}
					if (i > firstTwo) 
					{
						Swap(arr, i, firstTwo);
						firstTwo++;
					}
					break;
				case 1:
					if (i < firstOne)
					{
						firstOne = i;
					}
					if (i > firstTwo)
					{
						Swap(arr, i, firstTwo);
						firstTwo++;
					}
					break;
				case 2:
					if (i < firstTwo)
					{
						firstTwo = i;
					}
					break;
			}
			i++;		
		}
	}
	catch (IndexOutOfRangeException)
	{
		//Means we have run through the array
	}

}
private void Swap(int[] arr, int i, int j)
{
	int tmp;
	tmp = arr[i];
	arr[i] = arr[j];
	arr[j] = tmp;
}

- IC October 20, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Hi IC
Your code does not work if i change the input array.
int[] input = { 2, 1, 1, 0, 1, 2, 1, 2, 0, 0, 0, 1};
output = {1 0 0 0 0 1 1 1 1 2 2}

- ante December 17, 2015 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

I put 3 lines in case 1 lines. It worked for me.

case 1:
                            if (i < firstOne)
                            {
                                firstOne = i;
                            }
                            if (i > firstTwo)
                            {
                                Swap(arr, i, firstTwo);
                                if(firstTwo < firstOne)
                                {
                                    firstOne = firstTwo;
                                }
                                firstTwo++;
                            }
                            break;

- ante December 17, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

Use additional array to keep track the count for each input array item and reconstruct the original array with it. Thus, we can accomplish performance O(N).

class TestFun {
    class func sortZeroOneTwo(var input:[Int]) -> [Int] {
        
        var table = [Int](count: 3, repeatedValue: 0)
        
        for var i = 0; i < input.count; i++ {
            if table[input[i]] == 0 {
                table[input[i]] = 1
            } else {
                table[input[i]]++
            }
        }
        
        var index = 0
        for var i = 0; i < input.count; i++ {
            while index < table.count && table[index] <= 0 {
                index++
            }
            
            if index >= table.count {
                //nothing can be done here
                break
            }
            
            if table[index] > 0 {
                input[i] = index
                table[index]--
            }
        }
        
        return input
    }
}

- Anonymous October 18, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Sorry I forget to mention

He has clearly mentioned that we should traverse the array once

- NoMind October 18, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

Youd require O(3n) => O(n) time complexity.

track end of all the running arrays. Assume that the last 0 is at xth position, last 1 is at yth position, and last 2 is at zth position. s.t. x < y < z; for example {0,0,1,1,2,2,2} , then x = 1, y= 3, z = 6} .

Lets assume there is a additional 0, then we need 3 steps.
arr[x+1] = 0; x++;
arr[y+1] = 1; y++; // we know that arr[x+1] was 1 before we replaced it to 0.
arr[z+1] = 2; z++;

Now, x= 2, y= 4, z= 7. and array = {0,0,1,1,2, 2, 2}
For adding a 1, you'd just have to do 2 operations, ar[y+1] = 1; arr[z+1] = 2, and z++ y++
For 2, you simply do ar[z+1] = 2 and z++.

- Joshi of Vatsa. October 18, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Sorry I forget to mention

He has clearly mentioned that we should traverse the array once

Can you please provide the code ?

- NoMind October 18, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

By forcing you not to use High=N I think he is forcing you to count sort or bin sort.

- Abhi October 18, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Sorry I forget to mention

He has clearly mentioned that we should traverse the array once in O(N)

- NoMind October 18, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

static int[] FlagSort2(this int[] a)
    {
        var b = (int[])a.Clone();
        int zero = 0;
        int one = 0;
        int twos = 0;
        for (int i = 0; i < b.Length; i++)
        {
            switch (b[i])
            {
                case 0: Swap(ref b[zero++], ref b[one++]); break;
                case 1: one++; break;
                case 2: b[i] = 1; one++; twos++; break;
            }
        }

        for (int i = b.Length - twos; i < b.Length; i++)
        {
            b[i] = 2;
        }

        return b;
    }

- gerula October 18, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

We traverse the array once and calculate number of 0s, 1s and 2s and put it in the hashMap. In the second pass, we fill in the same array starting with zeros, once we are out of zeros, we go to the next key which is 1 so on.

This way we only scan the array once and do it in O(n) where n = number of elements in the array. So T = O(n), S = O(n)

- justaguy October 18, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

We can just count number of 0's, 1' s & 2's in the array in a single pass and use memset() to first update all 0's at once, then 1's and finally 2's. It saves lot of comparisons, space and time. memset() is supposed to be faster than accessing and updating individual elements. Most of the algorithms presented here are O(n). However, this approach needs only n comparisons.

We can attempt to reduce individual elements inspection in counting 0's, 1's and 2's by inspecting all the values or subset of the values together. However, this depends on the type of values in real application we expect. I am still working on this.

- vinodnalla October 19, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 2 vote

Use below method to do in position replace, and time complex should be O(n).

int left = 0, right = array.Length - 1, i = 0;
while (i < right)
{
	if (array[i] == 0)
	{
		Swap(array, i++, left++);
	}
	else if (array[i] == 1)
	{
		i++;
	}
	else if (array[i] == 2)
	{
		Swap(array, i++, right--);
	}
}

- renbin October 19, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

You don't know the lenght of the array.

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

Since you can only traverse the array once,

1. Create a new array.
2. Traverse the input array inserting the 0's you encounter at the front of our new array and inserting 2's from the back.
3. Whatever remains must be 1's so fill in the middle with 1's.

- Br October 20, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

This is the Dutch National Flag problem:
[http]s://en.wikipedia.org/wiki/Dutch_national_flag_problem

- blckembr October 21, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Use the same idea of partition the array in the quick sort. Take the mid value (1 in this case) as the pivotal value. Partition the array with less than the pivotal value and more than the pivotal value. Therefore it is a O(n) solution (with traverse the array only once) and O(1) space solution. Please refer to: cpluspluslearning-petert.blogspot.co.uk/2015/10/sort-array-with-three-distinct-numbers.html

Test

void TestSortArrayWithThreeDistinctNumbers()
{
    std::vector<int> arr;
    SortArrayWith3DistinctNumbers(arr, 0, 1, 2);
    assert(arr.empty() == true);

    arr = { 2, 2, 2, 0, 0, 0, 1, 1, 1 };
    SortArrayWith3DistinctNumbers(arr, 0 , 1, 2);
    assert(arr == std::vector<int>({ 0, 0, 0, 1, 1, 1, 2, 2, 2 }));

    arr = { 0, 1, 1, 0, 1, 2, 1, 2, 0, 0, 0, 1 };
    SortArrayWith3DistinctNumbers(arr, 0, 1, 2);
    assert(arr == std::vector<int>({ 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2 }));
}

- peter tang October 28, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

try with lo=0; mid=0;hi=0;

- D April 13, 2016 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

void swap(int* arr, int i, int j)
{
	if (i!=j)
	{
		int temp =arr[i];
		arr[i] = arr[j];
		arr[j] = temp;
	}
}

void sort(int * arr, int length)
{
	int lo = 0;
	int mid = 0;
	int hi = 0;
	while (hi < length)  // If length is not given then use whatever termination condition is allowed by the interviewer
	{
		switch (arr[hi])
		{
			case 0: {
				swap(arr, lo, hi);
				++lo;
				break;
			}
			case 1: {
				swap(arr, mid, hi);
				++mid;
				break;
			}
			case 2: {
				++hi;
				break;
			}
			default :{
				std::cout << "Error situation" << std::endl;
				break;
			}
		}
	}
}

- debparo664 April 13, 2016 | 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