Google Interview Question for Software Engineer / Developers


Country: United States
Interview Type: Phone Interview




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

Use a treemap to keep a chronologically sorted set of events that map to the amount of RAM created or destroyed. Iterate over the keys to keep a running total of RAM used while keeping track of the highest amount.

public class HighestRAM {
	private static List<LogEntry> logEntries = new ArrayList<>();
	private static Map<Long, Long> times = new TreeMap<>();
	
	public static void main(String[] args) {
		logEntries.add(new LogEntry(0, 100, 500, 1));
		logEntries.add(new LogEntry(10, 70, 300, 2));
		logEntries.add(new LogEntry(50, 200, 1000, 3));
		logEntries.add(new LogEntry(110, 220, 400, 4));
		logEntries.add(new LogEntry(175, 280, 750, 5));
		
		System.out.println("Highest RAM used is: " + findHighRAM());
	}
	
	private static long findHighRAM() {
		long curRAM = 0, highRAM = 0;
		
		for (LogEntry entry : logEntries) {
			times.put(entry.startTime, entry.ram);
			times.put(entry.endTime, -1 * entry.ram);
		}
		
		for (Map.Entry<Long, Long> event : times.entrySet()) {
			curRAM += event.getValue();
			if (curRAM > highRAM) highRAM = curRAM;
		}
		
		return highRAM;
	}
	
	static class LogEntry {
		public final long startTime;
		public final long endTime;
		public final long ram;
		public final long jobId;
		
		public LogEntry(long sTime, long eTime, long ram, long id) {
			startTime = sTime;
			endTime = eTime;
			this.ram = ram;
			jobId = id;
		}
	}	
}

- Brendan May 05, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Very Nice solution!

- Anonymous May 08, 2014 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

Very elegant solution!. Just one caveat.. In the case there there are 2 or more intervals sharing the same start or end values i.e a.start == b.start || a.end == b.end || a.start == b.end || a.end == b.start. In this case you would need to update the value for the key rather than just put it.
Must do something like this...

if (times.contains(timeValue)) {
	long oldVal = times.get(timeValue)
	long newVal = oldVal + (or -) entry.ram
	times.put(timeValue, newVal)
}

- Looper May 18, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Why couldn't we just make a max heap based on ram used and return the root? ?

- Anonymous June 18, 2014 | Flag
Comment hidden because of low score. Click to expand.
5
of 5 vote

Sort the set of log entries by start time.
Remove the earliest start time from that set and add to a priority queue that orders by end time.
Compare the earliest time entry of the set from the queue, and add or remove and update the ram usage.
Finish when set is empty.

Running time: O(n lg(n))

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

I haven't yet understood the approach. Can you please use an example to demonstrate the usage of your approach? This will be helpful!

- Victor May 06, 2014 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

Okay I will trace an example for you.

Given the a set of logs in the form of (start time, end time, ram usage):
1. 0, 100, 50
2. 50, 250, 1000
3. 100, 125, 240
4. 150, 175, 300

First you must sort them by start time, in this case it is already sorted, but the question does not guarantee that it does.

We will initially fill the priority queue with the first job.

Set: <2,3,4> PQ:<1>
We update the current ram usage: 50.
We compare it with the highest ram usage: Initially zero
and update it: 50.

Now we decide whether to remove the job from the PQ or insert another item into the PQ from the ordered set. This is determined by if the start time of the next job to be inserted (Job 2) is less or more than the top job of the PQ's end time (Job 1). In layman terms which will occur first, Job 1 ending or Job 2 starting. In this case job 2 starts before job 1 ends.

Additional note: In the corner case where one job ends as another starts which job do we pick? In real life this probably won't occur as the times are atomically defined (and depends on other factors like kernel design and parallel processing), but if the times were truncated we can have this situation occurring. Make sure you handle this case.

Set: <3,4> PQ:<1,2>
Update current ram: 1050
Update max ram: 1050 (was 50)

Now we compare job 3 start time with job 1 end time.
They are the same time. To handle this I can either pick one undeterministically (randomly) or define that either jobs always start before another one ends or vice versa. To make things simple I pick the latter.
Set:<4> PQ:<1,3,2>
Update current ram: 1290
Update max ram: 1290 (was 1050)

Now we compare job 4 start time with job 1 end time.
Job 1 ends before job 4 starts.
Set:<4> PQ:<3,2>
Update current ram: 1240
Update max ram: 1290 (unchanged when removing jobs)

Now we compare job 4 start time with job 3 end time.
Job 3 ends before job 4 starts.
Set:<4> PQ:<2>
Update current ram: 1000
Update max ram: 1290 (unchanged when removing jobs)


Now we compare job 4 start time with job 2 end time.
Job 4 starts before job 2 ends.
Set:<> PQ:<4,2>
Update current ram: 1300
Update max ram: 1300 (was 1290)

The set is now empty, no more jobs to add so we know that ram usage cannot increase any further.

Return the max ram.

- Anonymous May 06, 2014 | Flag
Comment hidden because of low score. Click to expand.
-1
of 1 vote

So its O(N^2) solution?

- Anonymous May 08, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Sort: O(n lg(n))
Delete from head of set at n times: n
Insert to priority queue n times : n lg(n)
Remove from priority queue at most n times: n lg(n)
Comparisons: 2n
Update current ram: 2n
Update max ram: n

- Anonymous May 08, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

The worst case is O(N^2), not O(Nlog(N)). Consider a situation that all tasks last until the last minute.

- Anonymous November 26, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

This looks like interval problem. Using interval tree we should be able to find the intersecting or overlapping intervals. peakRAM would be maximum intersection in given input collection.

- AlgoAlgae May 05, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Could you explain this more? Assuming I am understanding you correctly, wouldn't the maximum intersection mean the maximum number of jobs running at a single moment - a good heuristic, but the number of jobs doesn't necessarily equate to large ram usage (counterexample is one single large program).

- Anonymous May 05, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

agree with you. number of job may not really mean large ram. when we find intersections, we can compute the total ram and store in max heap. I should have said intersection with maximum ram usage.

- AlgoAlgae May 05, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

import java.util.*;

class logEntries{
	int startTime;
	int endTime;
	int RAMUsage;
	int id;
	logEntries(int startTime,int endTime, int RAMUsage,int id)
	{
		this.startTime=startTime;this.endTime=endTime;
		this.RAMUsage=RAMUsage;this.id=id;
	}
}
class entryNode
{
	int id;
	int time;
	int RAMUsage;
	entryNode(int id, int time, int RAMUsage)
	{
		this.id=id;
		this.time=time;
		this.RAMUsage=RAMUsage;
	}
}

public class peakRAM {
	
	public static Comparator<entryNode> entryComparator=new Comparator<entryNode>(){

		public int compare(entryNode n1, entryNode n2)
		{
			return (int)(Math.abs(n1.time)-Math.abs(n2.time));
		}
		
	};

	static int findPeakRam(ArrayList<logEntries> entries)
	{
		Queue<entryNode> entryPriorityQueue=new PriorityQueue<entryNode>(1,entryComparator);
		//Dividing the entries t
		for(logEntries en : entries)
		{
			entryPriorityQueue.add(new entryNode(en.id,en.startTime,en.RAMUsage));
			entryPriorityQueue.add(new entryNode(en.id,-en.endTime,en.RAMUsage));
		}
		//Polling the entries
		int Max=0,curr=0;
		while(true)
		{
			entryNode en=entryPriorityQueue.poll();

			if(en==null)
				break;
			//System.out.println("ID: "+en.id + " time : "+en.time + " RAMUsage : "+en.RAMUsage);
			if(en.time < 0)//
				curr-=en.RAMUsage;
			else 
			{
				curr+=en.RAMUsage;
				Max=Math.max(curr, Max);
			}
		}
		
		return Max;
	}
	public static void main(String[] args) {
		ArrayList<logEntries> entries=new ArrayList<logEntries>();
		entries.add(new logEntries(0, 100, 500, 1));
		entries.add(new logEntries(10, 70, 300, 2));
		entries.add(new logEntries(50, 200, 1000, 3));
		entries.add(new logEntries(110, 220, 400, 4));
		entries.add(new logEntries(175, 280, 750, 5));
		System.out.println(findPeakRam(entries));
		
	}

}

- Dinesh June 10, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

/*
public class LogEntry { 
public final long startTime; // start time of a job in millisec granularity 
public final long endTime; // end time of a job in millisec granularity. 
public final long ram; // the amount of ram the job occupies. 
public final long jobId; 
... constructor ... 
} 

running total of RAM 
| 
|             3GB 
|           ----- 
|      2GB 
|     ------ 
| 1GB                       ----------- 
|-----           ----------- 
| 
|____________________________________________________time 

Find the peakRAM when the input is a collection of LogEntry objects

for visual c++ 2005
*/

#include "stdafx.h"
#include <iostream>
#include <conio.h>
#include <algorithm>
#include <map>
#include <vector>
#include <list>
#include <iterator>
#include <math.h>
#include <numeric> 
#include <sstream>
#include <stack>
#include <string>

using namespace std;

struct LogEntry
{
	long startTime;
	long endTime;
	long ram;
	long jobId;

	LogEntry( long startTime_, long endTime_, long ram_,long jobId_)
	{
		startTime = startTime_;
		endTime = endTime_;
		ram = ram_;
		jobId = jobId_;
	}
};

struct MemEntry
{
	long nTime;
	long nMemAdd;

	MemEntry( long nTime_, long nMemAdd_ )
	{
		nTime = nTime_;
		nMemAdd = nMemAdd_;
	}
};

bool CompareFunc (MemEntry i,MemEntry j) 
{ 
	return (i.nTime < j.nTime); 
}

class Solution
{
public:
	static long CalcPeakMemory( vector<LogEntry> vecLogs )
	{
		vector<MemEntry> vecMem;
		for ( vector<LogEntry>::iterator it = vecLogs.begin(); it != vecLogs.end(); it ++ )
		{
			vecMem.push_back(MemEntry(it->startTime, it->ram));
			vecMem.push_back(MemEntry(it->endTime, -it->ram));
		}

		sort(vecMem.begin(), vecMem.end(), CompareFunc);

		long nResult = 0;
		long nResultTemp = 0;

		for ( vector<MemEntry>::iterator it2 = vecMem.begin(); it2 != vecMem.end(); it2 ++)
		{
			nResultTemp += it2->nMemAdd;
			nResult = max( nResult, nResultTemp );
		}

		return nResult;
	}
};


int _tmain(int argc, _TCHAR* argv[])
{
	vector<LogEntry> vecLogs;
	vecLogs.push_back(LogEntry( 0, 10, 15, 0));
	vecLogs.push_back(LogEntry( 0, 20, 30, 1));
	vecLogs.push_back(LogEntry( 15, 100, 50, 2));
	vecLogs.push_back(LogEntry( 50, 60, 20, 3));
	vecLogs.push_back(LogEntry( 100, 110, 5, 4));

	long nResult = Solution::CalcPeakMemory(vecLogs);

	cout << "The peakRAM is " << nResult << "." << endl;

	_getch();
	return 0;
}

- slfeng July 30, 2014 | Flag Reply


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