Google Interview Question
Software Engineer / DevelopersCountry: India
O(n) is claimed here as outer and inner radix sort - each runs a fixed number of iterations. For 4 byte integer, it's 32 if 2 bin is used for radix sort.
Without sorting? What does that even mean? Can I sort n-10 elements?
Anyway, a Theta(n^2) solution
// numbers: whose rank we need. Assumption: numbers are distinct (but code might still work)
// rank: the array in which to store ranks
// n: length of numbers (and rank) arrays.
void ComputeRank(int *numbers, int * rank, int n) {
for(int i = 0; i < n; i++) {
int curRank = 0;
// We assume the rank of a[0...i-1] is already computed.
// Now if we add a[i] to list, we need to update the ranks.
for (j = 0; j < i; j++) {
if (a[i] > a[j]) { // Update rank of a[i]
curRank++;
}
else { // A number smaller than a[j] has appeared. Update rank of a[j]
rank[j]++;
}
}
rank[i] = curRank;
}
}
Interviewer Told me that we can do it in O(N), i am wonder How , it has to be without sorting , also rank means order in which number comes in real number system in array
If your algorithm uses comparisons only, O(n) is not possible, as with the rank information you can compute the sort order, which has proved Omega(n log n) comparisons lower bound.
You might be able to do some bit-tricks etc.
In any case, the interviewer seems to be an idiot, so I don't think you(anyone other than Nimish) should worry too much about it.
Nimish, you are probably screwed already.
n^2 solution is not acceptible... you can sort yhe array in n*log(n) and assign the rankings in n
n*log(n)+n = n log(n).
looks like they are expecting time n
Perhaps I don't get what it is by mean "ranking". We findMin( ) and the second past divide arr[i] with min and deduct 1 from it so as to have min down to rank 0. It should not be too easy if min is not rank 0. In this case we have to compute GCD of all data in the list which is O(nlogn) and it is O(n) required by the interviewer.
void rank(int *A, int n, int *rank){
int i;
int min = A[0], max = min;
for(i = 1; i < n; ++i)
{
if (A[i] < min)
min = A[i];
else if (A[i] > max)
max = A[i];
}
// create a counting array, counts, with a member for
// each possible discrete value in the input.
// initialize all counts to 0.
int distinct_element_count = max - min + 1;
int *count = new int[distinct_element_count];
int *cum = new int[distinct_element_count]; //accumulated sum
for(i=0; i<distinct_element_count; ++i)
count[i] = 0;
for(i = 0; i < n; i++)
++count[A[i] - min];
cum[0] = count[0];
for(i=1; i<distinct_element_count; ++i)
cum[i] = cum[i-1] + count[i];
for(i = 0; i < n; i++) {
rank[i] = cum[A[i]-min] - count[A[i]-min];
count[A[i]-min]--;
}
for(i = 0; i < n; i++)
cout<< rank[i];
}
It's not O(n) solution. What if min = 1 and max = 2^32-1. This solution falls in pseudo-polynomial time algorithm, as the running time depends on "numeric value of the input", NOT "size of input".
Ref : en.wikipedia.org/wiki/Pseudo-polynomial_time
For above solution, it takes O(max) time to initialize count array. Moreover, space requriment is also O(max).
Input Array arr[6, 3, 9]
Find max element = 9
create another array tarr of size 9 all items initialized to -1;
Take rank counter int count = 0;
for(int i = 0; i < arr.Length; i++)
{
tarr[arr[i]] = count++;
}
for(int i = 0; i < tarr.length; i++)
{
if(tarr[i]!= -1)
{
print(tarr[i]);
}
}
This will print out the ranks.
Complexity O(n)
Maybe the interviewer just had count sort in his head. Provided n is small we can do something similar to count sort to get this ranking done in O(n). If we resort to comparisons then it is impossible to get the ranking in O(n), because if we can rank in O(n) with comparisons then we can as well make another pass on that ranked order and sort the array in O(n), which we all know cannot be true.
Following is the step we can do:
1. Find the maximum element in the array. O(n)
2. Replace array element by subtracting all the element by max. O(n)
3. Make a variable count initialize it with count= N-1.
4. now replace all elements by (count - element). O(n)
5. Finally obtained array gives the rank.
Total time: O(n)+O(n)+O(n)=O(n).
Correct me if wrong....
It's not O(n) solution. What if maximum element value = 2^32-1. This solution falls in pseudo-polynomial time algorithm, as the running time depends on "numeric value of the input", NOT "size of input".
Ref : en.wikipedia.org/wiki/Pseudo-polynomial_time
For above solution, it takes O(max) time to initialize count array. Moreover, space requriment is also O(max).
Can we just dump the entire list into a hash table O(n)?
I do not see and limitation on using extra space... :)
Input Array arr[6, 3, 9]
Find max element = 9
create another array tarr of size 9 all items initialized to -1;
Take rank counter int count = 0;
for(int i = 0; i < arr.Length; i++)
{
tarr[arr[i]] = count++;
}
for(int i = 0; i < tarr.length; i++)
{
if(tarr[i]!= -1)
{
print(tarr[i]);
}
}
This will print out the ranks.
Complexity O(n)
Input Array arr[6, 3, 9]
Find max element = 9
create another array tarr of size 9 all items initialized to -1;
Take rank counter int count = 0;
for(int i = 0; i < arr.Length; i++)
{
tarr[arr[i]] = count++;
}
for(int i = 0; i < tarr.length; i++)
{
if(tarr[i]!= -1)
{
print(tarr[i]);
}
}
This will print out the ranks.
Complexity O(n)
Input Array arr[6, 3, 9]
Find max element = 9
create another array tarr of size 9 all items initialized to -1;
Take rank counter int count = 0;
for(int i = 0; i < arr.Length; i++)
{
tarr[arr[i]] = count++;
}
for(int i = 0; i < tarr.length; i++)
{
if(tarr[i]!= -1)
{
print(tarr[i]);
}
}
This will print out the ranks.
Complexity O(n)
I have an ideea using hash table:
1) you add all the element in to a hash table.( and keep it sorted)
2) you go trough the table and for each row in the hash table you take the smallest number and the second one. then you go to the next row and until you find an element smaller then the second number you keep moving.
Basically you allways keep in track of the smallest 2 number and you go through the hash table over and over again to find all the element
I realy don't know how to estimate the complexity. O(N * K) where K is the size of the hash table ( that in the case that are all the same number or that all the number has the same module key value)
You just have to follow the logic from counting sort
1. Find the maximum element (k) in the array A. O(n)
2. Create an array C[1...k] and initialize it to 0. O(n)
3. For each A(i), set C[A(i)] = C[A(i)] + 1. O(n)
4. For each C(i) {i = 2...k}, C(i) = C(i) + C(i-1). O(n)
5. Create the rank array where R(i) = C[A(i)]. O(n)
Example
A: 3 4 1 5 8 2 9
C: 1 1 1 1 1 0 0 1 1 (from step 3)
C: 1 2 3 4 5 5 5 6 7 (from step 4)
R: 3 4 1 5 6 2 7 (from step 5)
PS: I assumed that the numbers in the array A are unique.
Hey stupid man, WHY DON'T ABOVE COMMENT MADE BY ANON.
2. Create an array C[1...k] and initialize it to 0. O(n)
You are such asshole that u claim it to O(n) where it's O(k). Leave away from here, and learn complexity first b4 posting some shits. Fucking moron!
if i have understood the question rightly then O(n) solution is there.
Make BST of the array. It will take O(N)
then traverse it Inorder and give every1 a rank. Again O(N)
now traverse in prefix order and get all the ranks you will get in the order the numbers were set in Array again O(N)
Over all O(N)
Heres what I could put together:
public class Rank {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
int A[] = {6,3,7,4,1,0,2,5};
int B[] = new int[A.length];
for(int i = 0; i < B.length; i++){
B[i] = 0;
}
int min = 1000000;
int setValue = 0;
for ( ; setValue < A.length; ) {
min = FindMinValue (A, B, setValue);
System.out.println( " Val: " + min + " " + setValue);
for(int i = 0; i < A.length; i++ ) {
if( (A[i] != min) && (B[i] == setValue) )
B[i]++;
}
setValue++;
}
System.out.println("Print Ranks");
for(int i = 0; i< B.length; i++) {
System.out.print(B[i] + " ");
}
}
private static int FindMinValue(int[] A, int[] B, int setValue) {
int min = 1000;
System.out.print( " Ranks: ");
for(int i = 0; i< A.length; i++) {
System.out.print( " " + B[i] + " ");
if( (min > A[i]) && (B[i] == setValue) )
min = A[i];
}
return min;
}
}
Using Radix sort on the value and the rank of each element, O(n) seems to be possible if we assume fixed (4 byte) int data type. For arbitrary length data type, this claim is invalid. It's obvious no comparison based approach can get an O(n) solution here.
A work through example to demonstrate the ranking computation.
- buried.shopno October 05, 2011