Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AMAZON Interview Question

Tags:

amazon

Given an N arrays of size K each.. each of these K elements in the N arrays are sorted, each of these N*K elements are unique. Choose a single element from each of the N arrays, from the chosen subset of N elements. Subtract the minimum and maximum element. Now, this difference should be least possible Minimum.. Hope the problem is clear :) :)

Sample:

N=3, K=3

N=1 : 6, 16, 67
N=2 : 11,17,68
N=3 : 10, 15, 100

here if 16, 17, 15 are chosen.. we get the minimum difference as 17-15=2.

like image 524
Manjunath Manoharan Avatar asked May 23 '11 07:05

Manjunath Manoharan


People also ask

Why is Amazon interview so hard?

Amazon's Behavioral Interview Is Tricky And Challenging Engineers applying to positions across the board go through a mandatory behavioral interview where they're assessed on a bunch of behavioral aspects. The questions are usually around Amazon's 14 leadership principles that the company values deeply.

Is it easy to crack interview for Amazon?

Amazon has a highly challenging interview process that evaluates your coding, problem-solving, and design capabilities. If you wish to uplevel your career by cracking Amazon's technical interview and landing a high-paying offer, this article will tell you exactly what you need to know.


2 Answers

I can think of O(N*K*N)(edited after correctly pointed out by zivo, not a good solution now :( ) solution.
1. Take N pointer initially pointing to initial element each of N arrays.

6, 16, 67
^ 
11,17,68
^
10, 15, 100
^ 

2. Find out the highest and lowest element among the current pointer O(k) (6 and 11) and find the difference between them.(5)
3. Increment the pointer which is pointing to lowest element by 1 in that array.

 6, 16, 67
    ^ 
 11,17,68
 ^
 10, 15, 100 (difference:5)
 ^ 

4. Keep repeating step 2 and 3 and store the minimum difference.

 6, 16, 67
    ^ 
 11,17,68
 ^
 10,15,100 (difference:5)
    ^ 


 6, 16, 67
    ^ 
 11,17,68
    ^
 10,15,100 (difference:2)
    ^ 

Above will be the required solution.

 6, 16, 67
    ^ 
 11,17,68
    ^
 10,15,100 (difference:84)
       ^ 

 6, 16, 67
        ^ 
 11,17,68
    ^
 10,15,100 (difference:83)
       ^ 

And so on......

EDIT:

Its complexity can be reduced by using a heap (as suggested by Uri). I thought of it but faced a problem: Each time an element is extracted from heap, its array number has to be found out in order to increment the corresponding pointer for that array. An efficient way to find array number can definitely reduce the complexity to O(K*N log(K*N)). One naive way is to use a data structure like this

Struct
{
    int element;
    int arraynumer;
}

and reconstruct the initial data like

 6|0,16|0,67|0

 11|1,17|1,68|1

 10|2,15|2,100|2

Initially keep the current max for first column and insert the pointed elements in heap. Now each time an element is extracted, its array number can be found out, pointer in that array is incremented , the newly pointed element can be compared to current max and max pointer can be adjusted accordingly.

like image 52
Terminal Avatar answered Jan 01 '23 05:01

Terminal


So here is an algorithm to do solve this problem in two steps:

First step is to merge all your arrays into one sorted array which would look like this:

combined_val[] - which holds all numbers
combined_ind[] - which holds index of which array did this number originally belonged to

this step can be done easily in O(K*N*log(N)) but i think you can do better than that too (maybe not, you can lookup variants of merge sort because they do step similar to that)

Now second step:

it is easier to just put code instead of explaining so here is the pseduocode:


int count[N] = { 0 }
int head = 0;
int diffcnt = 0;
// mindiff is initialized to overall maximum value - overall minimum value
int mindiff = combined_val[N * K - 1] - combined_val[0];
for (int i = 0; i &lt N * K; i++) 
{
  count[combined_ind[i]]++;

  if (count[combined_ind[i]] == 1) {
    // diffcnt counts how many arrays have at least one element between
    // indexes of "head" and "i". Once diffcnt reaches N it will stay N and
    // not increase anymore
    diffcnt++;
  } else {
    while (count[combined_ind[head]] > 1) {
      // We try to move head index as forward as possible while keeping diffcnt constant.
      // i.e. if count[combined_ind[head]] is 1, then if we would move head forward
      // diffcnt would decrease, that is something we dont want to do.
      count[combined_ind[head]]--;
      head++;
    }
  }

  if (diffcnt == N) {
    // i.e. we got at least one element from all arrays
    if (combined_val[i] - combined_val[head] &lt mindiff) {
      mindiff = combined_val[i] - combined_val[head];
      // if you want to save actual numbers too, you can save this (i.e. i and head
      // and then extract data from that)
    }
  }
}

the result is in mindiff.

The runing time of second step is O(N * K). This is because "head" index will move only N*K times maximum. so the inner loop does not make this quadratic, it is still linear.

So total algorithm running time is O(N * K * log(N)), however this is because of merging step, if you can come up with better merging step you can probably bring it down to O(N * K).

like image 37
zviadm Avatar answered Jan 01 '23 06:01

zviadm