Amazon Interview Question for Software Engineer / Developers


Country: United States
Interview Type: In-Person




Comment hidden because of low score. Click to expand.
1
of 1 vote

Haven't thought it thoroughly, but this is the rough idea:

Sort the starting and ending x-values of the building blocks. These are the "event points" (n*logn time)

Imagine a line sweeping from left to right, passing through each event point

At each event point, update the highest y-value, by either deleting an old building block or adding a new building block. The highest y-value marks the top of the side view that we are interested in. By maintaining a sorted data structure, like RB-tree, each update can be done in log(n) time.

After sweeping all the event points, we get the side view. There are O(n) event points, so the total time complexity is O(n*logn)

The code that implements this idea is non-trivial... I think it's hard to finish within the time of an interview.

- freshboy December 04, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

@freshboy:

i think the (x+w)'s are also event points.
Consider the situation where one building B ends at P, but no other building starts at the P. But there can be a building A that has started before B, but continues even after P

- bs1729 December 05, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

Bharat - can you elaborate on the question, it is unclear.

- Anonymous December 04, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

draw on paper as per co-ordinates to understand the problem better ..
ex: (5,10,25) ==> 4 co-ordinates of rectangle will become(x,y)=> (5,0),(5,10),(30,10),(30,0).

- bharat December 04, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

I believe this code should do the trick in log(N)*N time (going along the lines freshboy also suggested). It uses priorityqueues which remain sorted and insertions cost log(N), so since we do N insertions we have log(N)*N. One keeps track of the "houseEnds" points, and one of the largest houses in order. There are while loops in there that look worrying, but in fact we at most look at any element in either of the priority queues once so all added up they should work out to N over the whole run.

import java.util.Comparator;
import java.util.PriorityQueue;
import java.util.Vector;


public class DrawHouses {

	public static class House
	{
		public House(int _x, int _width, int _height)
		{
			x = _x;
			width = _width;
			height = _height;
		}
		public int x;
		public int width;
		public int height;
		public String strRep() {
			return x + ", " + width + ", " + height;
		}
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) 
	{
		//5R 10U, 5R 10 U, R 
		//(5,10,25),(10,20,15),(15,5,5)
		House h1 = new House(5, 25, 10);
		House h2 = new House(10, 15, 20);
		House h3 = new House(15, 5, 5);
		Vector <House> houses = new Vector();
		houses.add(h1);
		houses.add(h2);
		houses.add(h3);
		
		PriorityQueue <House> housesByHeight = new PriorityQueue(
				100, new Comparator <House>()
				{

					@Override
					public int compare(House arg0, House arg1) 
					{
						return arg1.height - arg0.height;
					}
					
				});

		PriorityQueue <House> housesByRemoval = new PriorityQueue(
				100, new Comparator <House>()
				{

					@Override
					public int compare(House arg0, House arg1) 
					{
						return (arg0.x+arg0.width) - (arg1.x+arg1.width);
					}
					
				});
		housesByHeight.offer(h1);
		housesByHeight.offer(h2);
		housesByHeight.offer(h3);
		while(!housesByHeight.isEmpty())
		{
			System.out.println(housesByHeight.poll().strRep());
		}
		System.out.println("\n\n");
		
		housesByRemoval.offer(h1);
		housesByRemoval.offer(h2);
		housesByRemoval.offer(h3);
		while(!housesByRemoval.isEmpty())
		{
			House h = housesByRemoval.poll();
			System.out.println(h.strRep() + " = " + (h.x + h.width));
		}
		System.out.println("\n\n");
		
		System.out.println(drawStr3(houses));
		//5R 10U 5R 10U 15R 10D 5R 10D
	}

	public static String drawStr3(Vector <House> houses)
	{
		String drawStr = "";
		PriorityQueue <House> housesByHeight = new PriorityQueue  <House>(
				100, new Comparator <House>()
				{
					@Override
					public int compare(House arg0, House arg1) 
					{
						return arg1.height - arg0.height;
					}
					
				});

		PriorityQueue <Integer> houseRemovalSpots = new PriorityQueue <Integer>(
				100, new Comparator <Integer>()
				{

					@Override
					public int compare(Integer arg0, Integer arg1) 
					{
						return  arg0 - arg1;
					}
					
				});

		int curMaxHeight = 0;
		int curX = 0;
		String s = "";
		for(int i = 0; i < houses.size(); i++)
		{
			if(houses.get(i).height > curMaxHeight)
			{
				s += "R" + (houses.get(i).x-curX) + ", " + "U" + (houses.get(i).height-curMaxHeight) + ", ";
				curMaxHeight = houses.get(i).height;
				curX = houses.get(i).x;
			}
			housesByHeight.offer(houses.get(i));
			houseRemovalSpots.offer(houses.get(i).x + houses.get(i).width);
			
			while((i == houses.size()-1 && !houseRemovalSpots.isEmpty()) 
					|| (i < houses.size()-1 && houseRemovalSpots.peek() < houses.get(i+1).x))
			{
				int removalSpot = houseRemovalSpots.poll();
				System.out.println("Checking out removal spot " + removalSpot);
				cleanQueue(housesByHeight, removalSpot);
				if(housesByHeight.isEmpty())
				{
					System.out.println("HousesByHeight is empty");
					s += "R" + (removalSpot-curX) + ", " + "D" + (curMaxHeight) + ", ";						
					break;
				}
				else
				{
					if(housesByHeight.peek().height < curMaxHeight)
					{
						System.out.println("Using removal spot " + removalSpot + " which contains " + housesByHeight.peek().strRep());
						s += "R" + (removalSpot-curX) + ", " + "D" + (curMaxHeight - housesByHeight.peek().height) + ", ";						
						curMaxHeight = housesByHeight.poll().height;
						curX = removalSpot;
					}
					else
					{
						System.out.println("Not using removal spot " + removalSpot);						
					}
				}
			}
		}
	
		return s;
	}
	
	public static void cleanQueue(PriorityQueue <House> pq, int xVal)
	{
		while(!pq.isEmpty() && (pq.peek().width + pq.peek().x) <= xVal)
		{
			System.out.println("Cleaning away " + pq.peek().strRep());
			pq.poll();
		}
	}

}

- Anonymous December 05, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

it's indeed a very elegant code, but i am wondering if (5,2,2),(10,1,2),(15,5,5) would give a counter example.

- bugbag July 01, 2013 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

it can be solved in O(n), with code around 30 lines in c++. Period.

- startup December 08, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

@startup : if u know the answer, why don't u write u'r algo here. Others will learn. Please write algorithm not code

- bharat December 08, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

I underestimated this question. freshboy's solution is as good as I can imagine. If you assume the x-coordinates are bounded, use count-sort, you can get it in O(n). And also, to determine the shadow-effect when walking through, you only need a stack to do it in constant time. So, if the input's x-coordinates are unbounded. O(nlgn), otherwise O(n)

- startup December 08, 2012 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

Here is an O(nlgn) solution in java. It creates a TreeMap of events (so that all events are in sorted order of occurrence), and maintains a maxHeap for masking active heights of buildings (If removing an element from Heap is not O(lgn), we can use another TreeMap instead of maxHeap).

static void getSideView (int[] dist, int[][] dim) {
    int numBuildings = dist.length;
    Map<Integer, Integer> events = new TreeMap<Integer, Integer>();
    for (int i = 0; i < numBuildings; i++) {
      events.put(dist[i], dim[i][0]);
      events.put(dist[i]+dim[i][1], (-1) * dim[i][0]);
    }
    int prevMask = 0;
    int prevIndex  = 0;
    Queue<Integer> activeHeights = new PriorityQueue<Integer>
         (numBuildings, Collections.reverseOrder());
    for (Map.Entry<Integer, Integer> e : events.entrySet()) { 
      int newMask = 0;                        
      if(e.getValue() > 0) {
        activeHeights.offer(e.getValue());
        newMask = activeHeights.peek();
        if(newMask > prevMask) {
          System.out.print((e.getKey() - prevIndex) + "R ");
          System.out.print((newMask - prevMask) + "U ");
          prevMask = newMask;
          prevIndex = e.getKey();
        }
      }
      else {
        activeHeights.remove((Integer)(e.getValue() * (-1)));
        if(activeHeights.isEmpty()) {
          newMask = 0;
        }
        else {
          newMask = activeHeights.peek();
        }
        if(newMask < prevMask) {
          System.out.print((e.getKey() - prevIndex) + "R ");
          System.out.print((prevMask - newMask) + "D ");
          prevMask = newMask;
          prevIndex = e.getKey();
        }
      }
    }
    System.out.println();
  }
  public static void main (String[] args) {
    int[] dist = new int[] {5,10,15};
    int[][] dim = new int[][] {{10,25},{20,15},{5,5}};
    getSideView(dist, dim);
  }

- famee December 27, 2012 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

If we can consider the total length of x-axis as n, then we have a simpler O(n) solution as follows:

static void getSideView (int[] dist, int[][] dim) {
    int numBuildings = dist.length;
    int totalWidth = 0;
    for (int i = 0; i < numBuildings; i++) {
      totalWidth = Math.max(totalWidth, dist[i] + dim[i][1]);
    }
    int[] mask = new int [totalWidth+1];
    for (int i = 0; i < numBuildings; i++) {
      for(int j = dist[i]; j < dist[i] + dim[i][1]; j++) {
        mask[j] = Math.max(dim[i][0], mask[j]);
      }
    }
    int prevMask = 0;
    int prevIndex = 0;
    for (int i = 0; i <= totalWidth; i++) {
      if(mask[i] == prevMask) {
        continue;
      }
      System.out.print((i-prevIndex) + "R ");
      if(mask[i] > prevMask) {
        System.out.print((mask[i] -prevMask) + "U ");
      }
      else if(prevMask > mask[i]) {
        System.out.print((prevMask - mask[i] ) + "D ");
      }
      prevMask = mask[i];
      prevIndex = i;
    }
    System.out.println();
  }

- famee December 27, 2012 | Flag


Add a Comment
Name:

Writing Code? Surround your code with {{{ and }}} to preserve whitespace.

Books

is a comprehensive book on getting a job at a top tech company, while focuses on dev interviews and does this for PMs.

Learn More

Videos

CareerCup's interview videos give you a real-life look at technical interviews. In these unscripted videos, watch how other candidates handle tough questions and how the interviewer thinks about their performance.

Learn More

Resume Review

Most engineers make critical mistakes on their resumes -- we can fix your resume with our custom resume review service. And, we use fellow engineers as our resume reviewers, so you can be sure that we "get" what you're saying.

Learn More

Mock Interviews

Our Mock Interviews will be conducted "in character" just like a real interview, and can focus on whatever topics you want. All our interviewers have worked for Microsoft, Google or Amazon, you know you'll get a true-to-life experience.

Learn More