Amazon Interview Question
Country: India
preliminary version:
there is a one-to-one correspondence between k-permutations of 'n' elements and falling factorial (FF-) numbers with 'n-1' digits
where only 'k' leading digits can be non-zero.
For example, an FF-number X with 5
digits {a0, a1, a2, a3, a4} is defined as:
X = a0 + 5*a1 + 5*4*a2 + 5*4*3*a3 + 5*4*3*2*a4
subject to conditions:
a0 < 5, a1 < 4, a2 < 3, a3 < 2, a4 < 1
or, equivalently, this is a number in a mixed radix system where
the base vector is given by [5, 4, 3, 2, 1]
Then, to convert a permutation of 'n' elements to an FF-number,
we do the following:
for each element a[i] of a permutation (except the last one) count the number of elements
with indices to the right of 'i' that are less
than a[i]
Example (permutations of 5 elements):
permutation -> FF-number
[5 3 2 1 4] -> [4 2 1 0]
[1 2 5 3 4] -> [0 0 2 0]
[2 4 3 5 1] -> [1 2 1 1] etc.
Now, suppose we wish to generate 3-permutations of [1 2 3 4 5 6]
in lexicographical order. For this we consider all FF-numbers with 5 digits
for which *only 3 leading digits can be non-zero*
We start with: [0 0 0 0 0] which corresponds to the first permutation:
[1 2 3 4 5 6] taking a length-3 prefix of the latter one yields [1 2 3]
and continue in this way:
FF-number -> [3-permutation][remaining part]
[0 0 0 0 0] -> [1 2 3][4 5 6]
[0 0 1 0 0] -> [1 2 4][3 5 6]
...
[2 1 2 0 0] -> [3 2 5][1 4 6]
[2 1 3 0 0] -> [3 2 6][1 5 6]
[2 2 0 0 0] -> [3 4 1][2 5 6]
...
[5 4 2 0 0] -> [6 5 3][1 2 4]
[5 4 3 0 0] -> [6 5 4][1 2 3]
I am a little confused here.. what do you mean without repetitions ?
I suppose for both permutations and combinations repetitions are not allowed, yet the difference is that combination is just a way of choosing N things out of M, thus order does not matter, while for permutations the order matters
Solution :
Let S be the symbol array in the increasing order
Let C be the given combination.
For each digit di starting from the left most in C and ask this question:
1. Is there a symbol x in S such that x > di and x does not occur in C for all j<I?
2. If so we are done place the right symbol, get out of this loop and call a function RestIt(…).
3. If not we move to i-1 digit in C and go back to step 1.
4. If we end up consuming C in the process then declare "cannot find number bigger than C".
In RestIt(…) we have the following situation an index j in C is filled (by step 1 and 2) by an x from S.
5. Inside RestIt(...) at j+1 in C we take the first symbol in S and see if occurs in C before j+1
6. If it does not, then fill the j+1th position in C by that element from s and go to step5 with j+2.
7. If it occurs move on to the next symbol in S and go to step 5 with the same j+1.
Example S = [1,2,3,4]
C = 2,4,3
At 3 in C by step 1 we do not have anything so we move on to 4,but this is that last index in S so we move on to 2, finally we have 3 in S so that 3>2 put that in place of 3. We have 343, give this (343) to RestIt(…). Now RestIt(…) will place 1 from S in place of 4in C and 2 from S in place of 3 in C giving us 312.
// assuming the symbol array in sorted order
public static void main(String[] args) {
// TODO Auto-generated method stub
char arr[] = next(new char[]{'2','5','4'}, new char[]{'1','2','3','4','5'});
System.out.println();
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
}
static char[] next(char cur[],char sym[]){
int index[] = new int [cur.length];
//creating an index table
for (int i = 0; i < sym.length; i++) {
for (int j = 0; j < cur.length; j++)
if(sym[i] == cur[j]){
index[j] = i;
break;
}
}
while(true){
for (int i = cur.length-1; i>=0; i--) {
if(i == 0 && index[i] == sym.length-1)
return null;
if(index[i]+1 >= sym.length){
index[i] = 0;
cur[i] = sym[index[i]];
}else{
index[i]++;
cur[i] = sym[index[i]];
break;
}
}
boolean good = true;
int m[]= new int[sym.length];
for (int i = 0; i < cur.length; i++) {
if(m[index[i]]==0)m[index[i]] = 1;
else {good = false; break;}
}
if(good)
return cur;
}
}
Hi,
How about we do this..
Consider the set S: {a0, a1,..., an-1}
and the given combination X: b0b1...bi-1
Step 1: We scan X from right and try to replace the digit with the next highest digit in the set such that no such digit is present to its left. If such a replacement is possible then we move to step 2 else we move to next rightmost digit. Let the position where the replacement is made be 'j'
Step2: Replace digits bj+1 to bi-1 with the minimum unique elements of S in sorted order that are not present to the left of 'j+1' position
Example: S: {1,2,3,4,5}
X: 345
The digit 5 cant be replaced as there is no higher digit
The digit 4 is replaced by 5 as '5' is not present to its left (X becomes 355)
Now the digit to the right of 5 in tens place becomes 1 as it is the minimum digit from S in sorted order.
Hence, next unique combination is 351
X: 254
Here 4 cant be replaced as next highest digit is 5 which is already present to its left
5 cant be replaced as as no such higher number in set
2 is replaced by 3 (we get the number 354) and digits to the right are replaced by 1 and 2 as they are minimum elements of S in sorted order (there are no elements to left of 3)
So we get 312
X:1235
We cant replace 5 as there is no higher element
We replace 3 by 4 to get 1245. Here we try to replace '5' with the digits of S in sorted order but 1,2 are present so we replace 5 by 3
So next combination is 1243
int find(int map[],int sym[],int size,int x,int max)
{
int i=0;
if (max == 1)
{
while (sym[i++] != x );
while( i < size )
{
if (map[sym[i]]==1)
{
return sym[i];
}
i++;
}
return x;
}
else if (max == 0)
{
while(sym[i] < x)
{
if(map[sym[i]]==1)
{
return sym[i];
}
i++;
}
return sym[i];
}
}
void function(int sym[],int size,int k,int x)
{
int map[10]={0};
int a[k];
for(int i=0;i<size;i++)
{
map[sym[i]]=1;
}
int n=x,l=k-1;
while(n!=0)
{
a[l]=n%10;
map[a[l--]]=-1;
n/=10;
}
int max,min;
for(l=k-1;l>=0;l--)
{
max=find(map,sym,size,a[l],1);
if(max!=a[l])
{
map[a[l]]=1;
a[l]=max;
map[max]=-1;
l++;
for(;l<k;l++)
{
min=find(map,sym,size,a[l],0);
map[a[l]]=1;
a[l]=min;
map[min]=-1;
//cout << "\nmin = " << min <<"; map[min] = "<<map[min];
}
break;
}
}
cout <<"Valid Symbols\n";
for(int i=0;i<size;i++)
cout<<sym[i]<<" ";
cout<<"\nEntered Number " <<x<<endl;
cout<<"Next Number ";
for (int i=0;i<k;i++)
{
cout<<a[i];
}
cout<<endl;
return;
}
- qiuziwang December 19, 2011