Microsoft Interview Question
Software Engineer in TestsGiven extra space, make use of SortedDictionary. Traverse the list once and store in SortedDictionary's value the number of times the key appears. Loop over the SortedDictionary.
see the range of values and assumption made in counting sort........... counting sort fails on large range
static void sortUnsortedArray()
{
int[] arr = new int[] { 1,3,2,1,6,45,6,7,3,67,43,499,9 };
int i=0, j=0, count = 0;
int[] tempArr=new int[500];
for (i = 0; i < arr.Length - 1; i++)
{
j = arr[i];
tempArr[j] = tempArr[j] + 1;
}
arr = new int[12];
int intAdd=0;
for (i = 0; i < tempArr.Length; i++)
{
if (tempArr[i] > 0)
{
count = tempArr[i];
while (count != 0)
{
arr[intAdd] = i;
count -= 1;
intAdd += 1;
}
}
}
}
Please correct this answer if any deviation.
To sort integers, I think most efficient way is using radix/bucket sort. It needs O(kn) time where k is < 20 for 64 bit int. So, we can claim that it's O(n) indeed. It needs O(n) space like merge sort & counting sort. Counting sort is a lot simpler than radix sort, but it needs space of O(max-min) where max (min) is largest (smallest) item in the array.
Hash the elements into a table.. Since there are duplicate values, associate a counter with each hash entry.. if there is a collision, increment the counter.. Once done (O(n)), read the table entry sequentially and multiply by counter and display the number that many number of times..
Though it's O(n) in term of time complexity, but it's O((max-min) space complexity, where max-min can be the full range of integer type.
Why not create build a multimap from the elements and print it out. I think keys in the map data structure are sorted??
Following are the steps to solve it in O(n):
1) Create a BST for the array
2) do inorder traversal
Please correct me if I am wrong
@jay - The best insert complexity for any "balanced" tree is min O(log n) amortized...and unbalanced BST has worst case O(n)...so your solution wont be O(n)...it might be worst case O(N^2) itself...
only counting sort/bucket sort would be O(n) worst case..
BTW its not written in question that we need worst case complexity?
Radix sort will do it in O(kn) where k = max possible no. of digits in an element.
for the example case-
1 1 1 2 2 4 444 44 5 5 45 45 6
1 1 1 2 2 4 4 5 5 6 444 44 45 45
1 1 1 2 2 4 4 5 5 6 44 45 45 444
Each of the above three steps takes O(n)
So the total time complexity becomes O(3n) which is basically O(n)
Radix sort doesn't perform any comparisons, so the fact that every element in the array is the same should have no effect on the algorithm. And, in fact, the algorithm doesn't decay to O(n^2) if all elements are duplicates.
OK, there are lot of misinformation with the comments and answer. First thing you need to know is that any kinda comparison sorting algorithm you pick will have a lower bound of O(nlogn), you cant do any better than that.
In that case, you will need to use bucket sort, count sort or radix sort. Which will amortize O(n) solution. I see answers like O(3n), there is no such notion in algorithm.
O(n) == O(3n)== O(100n). there are all same. linear time.
So the answer is non comparison sorting algorithms.
Easy answer would be, I find the max element and then create a dictionary from 0 to max.
Keys will be the sequence from 0 to max, and values would be the occurences.
At the end, you traverse the dictionary once and voila.
They say that in O(n) and it is only for integer. So we can the following:
int[] unsorted; //here is the input
int[] output;
int[] tmp;
int min=FindMax(unsorted);//O(n)
int max=FindMin(unsorted);//O(n)
int length=Math.Abs(max-min)
output=int[length];
tmp=int[unsorted.length];
for(int i=0;i<length;i++)//O(n)
{//Initializing
tmp[i]=0;
}
int inp;
for(int i=0;i<length;i++)//O(n)
{//Using the value as an index
inp=input[i];
tmp[inp-min]+=1;
}
int index=0;
int j=0;
for(int i=0;i<length;i++)//O(n)
{
if(tmp[i]!=0)//No occurrences
{index=0;
while(index<tmp[i])
{
output[j]=i-min;
j++;
index++;
}
}
//The final anwser is in output
//O(5n)==O(n)
}
I think radix sort would be the best. As its complexity is O(N*d) where d is negligible as compared to N.
Here is the implementation.
#include <stdio.h>
#include <limits.h>
#include <math.h>
int findMaxDigit(int *arr,int size)
{
int i,max=INT_MIN,n=0;
for(i=0;i<size;i++)
if(arr[i]>max)
max=arr[i];
while(max)
{
n++;
max/=10;
}
return n;
}
int isEmpty(int *r,int j)
{
return r[j]==-1;
}
void Enqueue(int (*Q)[10],int *f,int *r,int digit,int n)
{
if(f[digit]==-1)
f[digit]++;
Q[++r[digit]][digit]=n;
}
int Dequeue(int (*Q)[10],int *f,int *r,int digit)
{
int n=Q[f[digit]][digit];
if(f[digit]==r[digit])
f[digit]=r[digit]=-1;
else
f[digit]++;
return n;
}
void radixSort(int *arr,int size)
{
int i,j,k,Q[size][10],f[10],r[10],d,digit,top=-1;
d=findMaxDigit(arr,size);
for(i=0;i<size;i++)
f[i]=r[i]=-1;
for(i=0;i<d;i++)
{
for(j=0;j<size;j++)
{
digit=(arr[j]/pow(10,i));
digit%=10;
Enqueue(Q,f,r,digit,arr[j]);
}
top=-1;
for(j=0;j<10;j++)
{
while(!isEmpty(r,j))
arr[++top]=Dequeue(Q,f,r,j);
}
}
for(i=0;i<size;i++)
printf("%d ",arr[i]);
}
int main()
{
int arr[]={4,2,6,1,5,5,1,2,45,444,44,45,4,1};
radixSort(arr,sizeof(arr)/sizeof(arr[0]));
return 0;
}
i don think there's any sorting technique in O(n) time
- Anonymous May 15, 2011