Microsoft Interview Question
Developer Program EngineersCountry: India
Interview Type: Written Test
If you map a-z to 26 unique primes, it will have a space complexity of O(n), since you need to store it ..
it will take the same space complexity as hashing. BTW hashing doesnt need to do multiplication and the look up..
dont store it .. use if else statement..as you know which prime numbers u have assigned to which character
so, to reduce space complexity
if( ch =='a') ...
if(ch =='b') ....
...
and so on
What you do not understand however, is the fact that right now we are given a matrix with a definite number of elements (Order(n) does not apply since n isn't variable). There are 676 of them to be precise. When you talk about finding the multiplication of each row and column, you are visiting each element twice. Therefore, number of calculations performed are equal to 676*2. Instead, if you take two arrays of size 26 each and store the cumulative result, you will have to visit every element only once. [See the code I posted below], thus reducing the number of calculations to 676.
I guess this problem is aimed to emphasize that sometimes the order doesn't matter, a heavy computation that takes seconds to complete should be used as less as possible. Obviously, a code with lesser computations would run considerably faster, even if its time complexity is equal to some other code (with more computations).
Assigning prime number and multiplying seems a good method.But if you notice ,the situation is similar to the problem below.
problem:Given n consecutive numbers in an array,find whether one of the numbers is replaced with a duplicate of another number.
eq: 1,2,3,4,5 {4 is replaced with another 3} which makes it 1,2,3,3,5 .We need to find if such a replacement occurred or not.Find the sum of all numbers.subtract this from what the actual sum wouldve been had they been consecutive n*(n+1)/2
where n = 5 so real sum should have been 15.But actual sum is
14.Therefore duplicate exists.
Now replace the value of char with an integer value giving "a" value 1.We can get the missing character.Of course the complexity remains same.
take a[52][26] as extra space
now take first element in b[26][26] (given array) say index i=0,j=0 (consider the value inside this array as 0-25 instead of a-z) for example if b[0][0]='c';(here c considered as 'c'-'a'-1=2)
now assign a[0][2]=1 and a[26][2]=1 do like this for entire given array while filling in array a[][] if already it is 1 then the value is repeating if not the given array is perfectly valid.
give your suggestions
I think I can push your algor a little further.
you can use 52 integers instead of a 2-D array.. since one int can store 32 bits( in this case, you only need 26 bits)
Here I am using Set variable to check . For every row data will be inserted to this set variable , if after traversing a row size of set is not 26 then return false ;// condition is not satisfied , otherwise go for checking next row .
public boolean checkArray(char array[][])
{
int rowLimit=array.length;
int colLimit=array[0].length;
int i,j;
HashSet<Character> set=new HashSet<Character>();
for(i=0;i<rowLimit;i++)
{
for(j=0;j<colLimit;j++)
{
set.add(array[i][j]);
}// End of inner for loop
if(set.size()!=26)
{
return false; // each row is not having char from a-z
}
else
{
set.clear();
}
}// End of outer for loop
return true; // each row satisfy required condition
}
public static final int OR= 0x3ffffff;
public static boolean isValid(char[][] array, int pos, int[] orRow, int[] orCol)
{
if(pos==array.length-1)
return (orCol[pos]|array[pos][pos])==OR&&(orRow[pos]|array[pos][pos])==OR;
int cumRow= orCol[pos], cumCol= orRow[pos];
for(int i=pos; i<array.length; i++)
{
cumRow|=0x1<<((int)((int)array[pos][i]-(int)'a'));
cumCol|=0x1<<((int)((int)array[i][pos]-(int)'a'));
orRow[i]|=0x1<<((int)((int)array[pos][i]-(int)'a'));
orCol[i]|=0x1<<((int)((int)array[i][pos]-(int)'a'));
}
return (cumRow==OR&&cumCol==OR)?isValid(array, pos+1, orRow, orCol):false;
}
Here is solution. It is O(n*n) and additional 8 bytes for storing bits. (does not count local variables). Written on C#. It is possible to eliminate "prev" variable by using "|=" operator, but it will be hard to read.
static int getCharIndex(char c)
{
return c - 'a';
}
static bool checkArray(char[,] a)
{
const int maxChars = 26;
if (a == null || a.Rank != 2)
return false;
int N = a.GetUpperBound(0) + 1;
if (N > maxChars || a.GetUpperBound(1) + 1 != N)
return false;
for (var i = 0; i < N; i++)
{
uint row = 0;
uint col = 0;
for (var j = 0; j < N; j++)
{
int iRow = getCharIndex(a[i, j]);
if (iRow < 0 || iRow >= N)
return false;
uint prev = row;
row = row | (1u << iRow);
if (prev >= row)
return false;
int iCol = getCharIndex(a[j, i]);
if (iCol < 0 || iCol >= N)
return false;
prev = col;
col = col | (1u << iCol);
if (prev >= col)
return false;
}
}
return true;
}
Hey!! I am missing something here, can't we just sum up all the elements for each row and each column to check if all sums are the same unique value. ?
Each element is accessed once
#include <stdio.h>
void main()
{
char arr[26][26];
int i,j,k=0;
for(i=0;i<26;i++)
{
k = i;
for(j=0;j<26;j++)
{
arr[j][k] = i + 97;
k--;
if(k==-1)
k=25;
}
}
for(i=0;i<26;i++){
for(j=0;j<26;j++)
{
printf("%c ",arr[i][j]);
}
printf("\n");
}
}
Complexity: O(n^2)
const int N = 26;
static inline unsigned long get_character_mark(const char a)
{
return (1UL << a - 'a');
}
bool judge_matrix(char arr[N][N])
{
unsigned long sum_arr[2][N];
memset(sum_arr, 0, sizeof(sum_arr));
for(int i = 0; i < N; ++i)
{
for(int j = 0; j < N; ++j)
{
const unsigned long mask = get_character_mark(sum_arr[i][j]);
if((sum_arr[0][i] & mask) || (sum_arr[1][j] & mask))
{
return false;
}
else
{
sum_arr[0][i] |= mask;
sum_arr[1][j] |= mask;
}
} // for
} // for
return true;
} // judge_matrix
My approach:
Compute an XOR of a to z (a^b^c...z).
XOR this value with each row and column. If the row/column contains the set(a-z), this XOR will return 0.
The time complexity in this case will still be O(n*n), but we have at least removed the space complexity.
No, it's not.
If characters a to z are 8-bit ascii values we have at most 2^8 (=256) possible values for xor result. On the other hand for each row/column there are choose(51,26) possible ordered combinations with repetition, which is far greater number.
Therefore, there are at least two different combinations which give the same xor result.
you cant reduce the time complexity further than O(n2) becoz... u have to visit each element at least once , ofcourse, so, tc > O(n2).
- guest travis August 22, 2012further dont use hashing to check for rach rows and columns as it will take space complexity of O(n).
instead,
assign each character from a to z a unique prime number.
find the multiplication of these 26 prime numbers, say m
now find the multiplication of 26 characters present in each rows and columns
if each rows and each columns multiplication match to m.
so return true
else return false..
furthermore, dont think abt to reduce time complexity further.. u cant
u have to go through each element at least for once