Google Interview Question for Software Engineers


Country: United States
Interview Type: In-Person




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

Sort start times with an nlogn sorting algorithm and store it.
Sort end times with an nlogn sorting algorithm and store it.

We traverse sorted start times and add to an accumulator, but after traversing one start time, we traverse as many end times as needed to "catch up" to the start time and we subtract that from the accumulator. Take the max of accumulator vs the current max at each traversal.

O(nlogn)

- zd September 21, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Simple, Correct, and Beautiful

- koosha.nejad October 16, 2015 | Flag
Comment hidden because of low score. Click to expand.
3
of 3 vote

Here's my O(nlogn) solution.Basically it's the same as what @zd said.

More explanations:
Think of time intervals as a bunch of segments (with start and end points). Now we want to find a point which has most weighted(memory usage) intersection with other segments.

For sure the answer is one of the start points.
We can add all start and end points to a vector (with their type(start or end) and their original index in segments) and sort them.
Now we start from left to right, and keep track of sum of all memory usages which are currently having intersection with each other.At each end point we just need to subtract the memory usage of that segment, and at each start point just add the new memory usage and see whether we have a maximum answer so far.

The tricky point is that in case of equal dates(times), start points should be on the left of end points.

Here's the my implementation in C++.

int findBusyHour(vector< pair<pair<int,int>,int > > times)
{
	int N=times.size();

	vector< pair<int, pair<int,int> > > points; // (time,(isEndPoint,OriginalIndex))
	for (int i=0;i<N;i++){
		points.push_back({times[i].first.first,{0,i}});
		points.push_back({times[i].first.second,{1,i}});
	}

	sort(points.begin(),points.end());

	int cur=0,maxi=0;
	int ans=0;
	for (int i=0;i<2*N;i++){
		int ind=points[i].second.second;
		int isEnd = points[i].second.first;
		int h=points[i].first;
		if (isEnd){//end point
			cur-=times[ind].second;
		}
		else{
			cur+=times[ind].second;
			if (cur>maxi){
				maxi = cur;
				ans = h;
			}
		}

	}

	return ans;
}

- MehrdadAP September 21, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

I think I found an issue with your code..at first I didn't understand it, so I started poking it and printing debug info, I then came up with the following set:

100207 100210 4
100209 100209 1
100209 100209 1
100209 100209 1
100209 100209 1
100209 100209 1
100210 100211 10

The issue comes from the fact that we only traverse 0-N (while the 'points' vector is 2N - so if there's a start time AFTER N it will not get found (see debug dump below of the sorted points vector). I believe the solution is to break up the sort by start and end and proceed to add/sub from there, such that we can verify that all start points will get hit.

T:100207, End:0, idx:0
T:100209, End:0, idx:1
T:100209, End:0, idx:2
T:100209, End:0, idx:3
T:100209, End:0, idx:4
T:100209, End:0, idx:5
T:100209, End:1, idx:1
T:100209, End:1, idx:2
T:100209, End:1, idx:3
T:100209, End:1, idx:4
T:100209, End:1, idx:5
T:100210, End:0, idx:6
T:100210, End:1, idx:0
T:100211, End:1, idx:6

- Greg October 05, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

I think I found an issue with your function. At first I didn't understand it (too many pairs, I think :-P) so I started poking it and printing debug info, then I came up with the following log:

100207 100210 4
100209 100209 1
100209 100209 1
100209 100209 1
100209 100209 1
100209 100209 1
100210 100211 10

It will tell you it's 100209 (with a usage of 9), but in reality it's 100210 with a usage of 10.
The problem comes from the fact that the 'points' vector is 2N in length, but we only traverse N of it. Therefore, any "start" events which occur AFTER N in the sorted points vector are not found (see debug dump below). I believe the solution involves scanning all start nodes first, so we can verify we find them all. Though I'm not entirely sure if this is achievable by simply re-ordering the vector so that "end" is sorted first. Thoughts?

T:100207, End:0, idx:0
T:100209, End:0, idx:1
T:100209, End:0, idx:2
T:100209, End:0, idx:3
T:100209, End:0, idx:4
T:100209, End:0, idx:5
T:100209, End:1, idx:1 // Last point considered
T:100209, End:1, idx:2
T:100209, End:1, idx:3
T:100209, End:1, idx:4
T:100209, End:1, idx:5
T:100210, End:0, idx:6
T:100210, End:1, idx:0
T:100211, End:1, idx:6

- Greg October 05, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Your approach works correctly, but when you try to determine the max (the loop after the sort) you need to iterate a full 2*N times or else it will fail when logs like below are given which results in the highest usage occurring in the second half of the sorted points vector - so it will never be found in N iterations:

100207 100210 4
100209 100209 1
100209 100209 1
100209 100209 1
100209 100209 1
100209 100209 1
100211 100211 10

- Greg October 05, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@Greg: You're completely right, I forgot to write 2*N in for loop. Updated :)

- MehrdadAP October 26, 2015 | Flag
Comment hidden because of low score. Click to expand.
2
of 2 vote

Split log to 2 nodes, start and end. Start node has positive memory and end node has negative memory. Sort all nodes, and process each nodes.

Example)
100207 100208 2
100305 100307 5
100207 100209 4

split ==>

100207 2
100208 -2
100305 5
100307 -5
100207 4
100209 -4

sort ==>

100207 2
100207 4
100208 -2
100209 -4
100305 5
100307 -5

#include <iostream>
#include <map>

using namespace std;

int findBusyHour(int log[][3], int n) {
	multimap<int, int> nodes;
	multimap<int, int>::iterator it;
	int i, maxHour, maxMemory, hour, memory, released;

	i = 0;
	while (i < n) {
		nodes.insert(make_pair(log[i][0], log[i][2]));
		nodes.insert(make_pair(log[i][1], -log[i][2]));
		i++;
	}

	maxHour = -1;
	maxMemory = 0;
	hour = -1;
	memory = 0;
	released = 0;

	it = nodes.begin();
	while (it != nodes.end()) {
		if (hour != it->first) {
			hour = it->first;
			memory += released;
			released = 0;
		}
		if (it->second > 0) {
			memory += it->second;
			if (memory > maxMemory) {
				maxHour = hour;
				maxMemory = memory;
			}
		} else {
			released += it->second;
		}
		it++;
	}

	return maxHour;
}

int main(int argc, char* argv[]) {
	int log[][3] = {
		{100207, 100208, 2},
		{100305, 100307, 5},
		{100207, 100209, 4},
		{111515, 121212, 1}
	};

	cout << findBusyHour(log, 4) << "\n";

	return 0;
}

- kyduke September 22, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Yes, if the start times and end times are close together for all entries, you'll get roughly ~O(n). The trade off is increased memory complexity.
If start and end times are far apart however, you'll get much higher space and time complexity.

- Joey September 29, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Really cool idea, but the code is overly complicated. You could just sort your pairs by time (in case time is equal positive memory usage comes first). Then it's just the matter of going through the pairs and computing memory usage at each moment.

- damluar October 20, 2015 | Flag
Comment hidden because of low score. Click to expand.
2
of 6 vote

It is a classic problem, we can use a cumulative array

static const int MAX = 111225;

int findHeighestMemoryUsageHour() {
	int usagePerHour[MAX] = {0};
	int start, end, usage;
	while (cin >> start >> end >> usage) {
		start -= 10000;
		end -= 10000;
		usagePerHour[start] += usage;
		usagePerHour[end + 1] -= usage;
	}

	for (int i = 1; i < MAX; ++i)
		usagePerHour[i] += usagePerHour[i - 1];

	int res = 0, maxUsage = 0;
	for (int i = 0; i < MAX - 1; ++i) {
		if (usagePerHour[i] > maxUsage) {
			res = i;
			maxUsage = usagePerHour[i];
		}
	}

	return res + 10000;
}

- malinbupt September 22, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
1
of 1 vote

Curious, why do you loop twice at the end from 0 to MAX?
Couldn't you just combine these two loops and keep a running "current" usage and compare that to maxUsage?

While the runtime of this is faster because it doesn't require a sort, if this were put to use in a real-world situation with say, epoch seconds as indices, would there be any possible memory consumption issues?

It also seems you could speed this up a bit by tracking the min and max times in your top while loop to use as start and end points for your for loop(s).

- Rob September 22, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Thank you very much, Rob. You are right.

I just offer a thought, not yet optimized the code.

If epoch seconds as indices, maybe we can use "discrete coordinate" to reduce the memory usage. But in this case, we also need to sort the coordinates' array. If the coordinates' array is still large,we can divide the time duration into segments and process each segment. In this case, we need to read the file multiple times.

- malinbupt September 23, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

This is drivel that does not solve anything.

- haldokan October 02, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

You are using a HUGE array, it specifically states that this is not acceptable

- koosha.nejad October 16, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

This "solution" goes through large array even if only a single log record was passed to it.
The array is not required. You use it to order start and end times.
Instead you could just have 2 arrays of log records: one sorted by start time and another by end time. Or you could have a single array where you put both start and end times. Then you can sort and process it.

- damluar October 20, 2015 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

Isnt it the classic problem of finding continuous max sum?

- Rakesh September 26, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

if we simplify this problem then it would look like following:
((startTime,endTime),val):
((1,2),2) ((3,4),5) ((1,3),4) ((5,6),1)
now we sort the start time and then we merge intervals along with the values. As we are merging we also keep track of the max value and in the end we return the interval with max value.

Sorting takes O(nlogn) + merging takes O(n), so running time is O(nlogn)

- justaguy September 21, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Is this a possible solution that doesn't involve sorting?

Since time is MMDDHH, the maximum integer is 123124 or 130000 to be safe. Maybe we can create an array, int[130000], where each element represents the memory usage. The index represents the "time". As we process each log entry, we can fill in the array. For instance, processing

100305 100307 5

means adding 5 to the array at each index 100305 to 100307. Then afterwards, we run a for loop to determine the maximum memory usage.

Actually I think this is similar to what malinbupt implemented? I only know c# so I'm not
exactly sure what's going on.

- dre September 22, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Yes, dre. Your solution are the same as me. Rob has raised a good question, you can try to solve it.

- malinbupt September 23, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 2 vote

Worst case time complexity => O(n)
Worst case space complexity (excluding the input itself) => O(1)

MMDDHH time format indicates that that input space ranges from 010101 to 123124 which is 8928 values.

With this observation in mind, we can create two hash maps (you can use arrays if you like). For each start time, update the value to 'value in the hash map + value (memory occupied) of the current start time'. Lets call this map as mapA.

Do the same for end times in a separate hash map. Lets call this map as mapB.

Now maintain an List bound by size 4 'maxStartTimeList'. A value for maximun size seen so far. Lets call it 'maxSize'. Also, the current size 'currSize'

Iterate over mapA. for each key in mapA and corresponding key in mapB get their values. v1 and v2.

Then for each key,

currSize = currSize + v1 - v2
if(currSize == maxSize) {
    maxStartTimeList.add(currStartTime);
    if(maxStartTimeList.size() == 4) {
        return maxStartTimeList;
    }
} else if(currSize > maxSize) {
    replace the list with a new one and add the startTime to that list
} else just move on.

Note that you don't need mapA and mapB in order of 'startTime' or 'endTime'

(Please correct me if I am wrong :-P. Working on the code next.)

- nikul September 22, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Worst case time complexity => O(n)
Worst case space complexity => O(1)

MMDDHH time format indicates that that input space ranges from 010101 to 123124 which is 8928 values.

With this observation in mind, we can create two hash maps (you can use arrays if you like). For each start time, update the value to 'value in the hash map + value (memory occupied) of the current start time'. Lets call this map as mapA.

Do the same for end times in a separate hash map. Lets call this map as mapB.

Now maintain an List bound by size 4 'maxStartTimeList'. A value for maximun size seen so far. Lets call it 'maxSize'. Also, the current size 'currSize'

Iterate over mapA. for each key in mapA and corresponding key in mapB get their values. v1 and v2.

Then for each key,

currSize = currSize + v1 - v2
if(currSize == maxSize) {
    maxStartTimeList.add(currStartTime);
    if(maxStartTimeList.size() == 4) {
        return maxStartTimeList;
    }
} else if(currSize > maxSize) {
    replace the list with a new one and add the startTime to that list
} else just move on.

(Please correct me if I am wrong :-P )

Note that you don't need mapA and mapB in order of 'startTime' or 'endTime'

- nikulkni September 22, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Wouldn't you need to sort the keys? Otherwise you're going to be iterating in hash-order.

- moose September 22, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Thanks moose@. I hadn't read earlier responses to this question. So, in that case we can use a TreeMap.

- nik September 22, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

No matter what you use, I strongly believe O(n) time is not possible

- koosha.nejad October 16, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

How can my solution be improved?

#input:100207 100208 2
			#October 02 7am -> 8am  (memory:2)
			#100305 100307 5
			#111515 121212 1
			#max is 123124


#if two intervals intersect, do a union
#otherwise, add the interval 

def busiestHour(timeList):
	start = [int(x) for x in timeList[::3]]
	end = [int(x) for x in timeList[1::3]]
	memory = [int(x) for x in timeList[2::3]]
	zipped = zip(start,end,memory)
	abc = [0]*123125
	for i in zipped:
		for j in range(int(i[0]),int(i[1])+1):
			abc[j] = abc[j] + i[2]

	hour = max(abc)
	return abc.index(max(abc)))		
	

log = "100207 100208 2\n100305 100307 5\n100207 100209 4\n111515 121212 1"
timeSet = log.split()

print(busiestHour(timeSet))

- Anonymous September 22, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

I couldn't understand the problem, why the answer to given input is 100207 ? Please explain if someone read this.

- JoyZombie September 22, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Apologize for the unclearness. Because there are two time slots that contains 100207, so we add them up. So at time 100207, there are 4+2 = 6 memory usage.

- aijackmoore September 22, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

what should happen if I have additional log entry like 100205 100207 5 in your example????

- rajat.shrivastava.aw September 22, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

In this example, the time slots are inclusive if that is the point of your question. So 100205 100207 5 will contain both 100205 and 100207

- aijackmoore September 23, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

Most of the solution I am seeing assumes that we have memory large enough to store all the logs in memory for sorting. How would solution change if I cannot bring all the nodes in memory for sorting??? Just curious!!!!!

- rajat.shrivastava.aw September 22, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Run map reduce/external sort?

- random September 22, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

since we are dealing with limited number of keys.. I don't think we need to use map reduce or external sort. I think idea similar to counting sort can be used.

- rsrs3 September 23, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

public int getHourMax(String[] logs)
{
	int[] usageData=new int[123100-10100+1];///123100 represents 12/31 at hour 00 10100 represents 01/01/ hour 00
	int maxUsage=Integer.MIN_VALUE();
	int maxUsageHour=0;
	for(String s:logs)
	{
		int[] arr=s.split();//Split the log entry into three elements (start date and time, end date and time, usage)
		//get start 
		int start=Integer.parseInt(arr[0]).intValue();
		//get end 
		int end=Integer.parseInt(arr[1]).intValue();
		//get usage
		int usage=Integer.parseInt(arr[2]).intValue();
		
		//find the indices in the array corresponding to start and end. Add usage to each of the values in these positions. Keep track of the maximum 
		//usage amount encountered at each update to the array
		int i=start-10100;
		int j=end-10100;
		 while(i<=j)
		 {
			usageData[i] += usage;
			if(usageData[i]>maxUsage)
			{
					maxUsage=usageData[i];
					maxUsageHour=i+10100;
			}
		 }
	}
	return maxUsageHour;
}

//Worst time complexity O(n). Space complexity is O(1)

- divm01986 September 23, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

I really like Malinbupt's approach. Here it is in Java:

public class Log {
	
	private static final int MAX = 123124;
	
	private int start;
	private int end;
	private int usage;
		
	public Log(int start, int end, int usage) {
		this.start = start;
		this.end = end;
		this.usage = usage;
	}
	
	public static int findPeak(Log... logs) {
		int [] usageArray = new int[MAX + 2];
		for (int i = 0; i < logs.length; ++i) {
			usageArray[logs[i].start] += logs[i].usage;
			usageArray[logs[i].end + 1] -= logs[i].usage;
		}
		
		int maxSoFar = usageArray[0];
		int time = 0;
		for (int i = 1; i <= MAX; ++i) {
			usageArray[i] += usageArray[i - 1];
			if (usageArray[i] > maxSoFar) {
				maxSoFar = usageArray[i];
				time = i;
			}
		}
		
		return time;
	}

}

O(N) time, O(N) space

- Iuri Sitinschi September 23, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;


class Log{
	
	
	public Log(int startTime, int endTime, int cpu) {
		super();
		this.startTime = startTime;
		this.endTime = endTime;
		this.cpu = cpu;
	}
	int startTime;
	int endTime;
	int cpu;
}

public class CpuHighest {


	public static void main(String[] args){
		List<Log> logs = new LinkedList<Log>();
		logs.add(new Log(100207,100208,2));
		logs.add(new Log(100305,100307,5));
		logs.add(new Log(100207,100209,4));
		logs.add(new Log(111515,121212,1));
		Hashtable<Integer,Integer> hourlyCpuMap = new Hashtable<Integer,Integer>();
		int max=0;
		int time=0;
		for(Log l : logs){
			int tDiff = l.endTime - l.startTime;
			int avgCpu = l.cpu / tDiff;
			for(int i=l.startTime; i<=l.endTime; i++){
				Integer hourlyCpu = hourlyCpuMap.get(i);
				if(hourlyCpu!= null)
					hourlyCpuMap.put(i, hourlyCpu+avgCpu);
				else
					hourlyCpuMap.put(i,avgCpu);
				if(hourlyCpu != null && hourlyCpu > max){
					max = hourlyCpu;
					time = i;
				}
			}
			
		}
		
		System.out.println(time);

	}

}

- Sankar September 23, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;


class Log{
	
	
	public Log(int startTime, int endTime, int cpu) {
		super();
		this.startTime = startTime;
		this.endTime = endTime;
		this.cpu = cpu;
	}
	int startTime;
	int endTime;
	int cpu;
}

public class CpuHighest {


	public static void main(String[] args){
		List<Log> logs = new LinkedList<Log>();
		logs.add(new Log(100207,100208,2));
		logs.add(new Log(100305,100307,5));
		logs.add(new Log(100207,100209,4));
		logs.add(new Log(111515,121212,1));
		Hashtable<Integer,Integer> hourlyCpuMap = new Hashtable<Integer,Integer>();
		int max=0;
		int time=0;
		for(Log l : logs){
			int tDiff = l.endTime - l.startTime;
			int avgCpu = l.cpu / tDiff;
			for(int i=l.startTime; i<=l.endTime; i++){
				Integer hourlyCpu = hourlyCpuMap.get(i);
				if(hourlyCpu!= null)
					hourlyCpuMap.put(i, hourlyCpu+avgCpu);
				else
					hourlyCpuMap.put(i,avgCpu);
				if(hourlyCpu != null && hourlyCpu > max){
					max = hourlyCpu;
					time = i;
				}
			}
			
		}
		
		System.out.println(time);

	}

}

- Anonymous September 23, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Your avgCpu calculation is wrong, because you can't just subtract times to get the number of hours in an interval: you are including a variable number of inadmissible hours (e.g. day of month > 31, hour of day > 24).

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

import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;


class Log{


public Log(int startTime, int endTime, int cpu) {
super();
this.startTime = startTime;
this.endTime = endTime;
this.cpu = cpu;
}
int startTime;
int endTime;
int cpu;
}

public class CpuHighest {


public static void main(String[] args){
List<Log> logs = new LinkedList<Log>();
logs.add(new Log(100207,100208,2));
logs.add(new Log(100305,100307,5));
logs.add(new Log(100207,100209,4));
logs.add(new Log(111515,121212,1));
Hashtable<Integer,Integer> hourlyCpuMap = new Hashtable<Integer,Integer>();
int max=0;
int time=0;
for(Log l : logs){
int tDiff = l.endTime - l.startTime;
int avgCpu = l.cpu / tDiff;
for(int i=l.startTime; i<=l.endTime; i++){
Integer hourlyCpu = hourlyCpuMap.get(i);
if(hourlyCpu!= null)
hourlyCpuMap.put(i, hourlyCpu+avgCpu);
else
hourlyCpuMap.put(i,avgCpu);
if(hourlyCpu != null && hourlyCpu > max){
max = hourlyCpu;
time = i;
}
}

}

System.out.println(time);

}

}

- Sankar September 23, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

public class GoogleLogs {

    private static int[] durationLogs;
    public static final int MAX = 123123;
    public static final int MIN = 10100;

    public static void main(String[] args) throws IOException {

        durationLogs = new int[MAX - MIN + 1];
        String dirPath = args[0];
        String fileName = args[1];
        // run loop in case of multiple files
        readFile(dirPath, fileName);
        int maxUsage = Integer.MIN_VALUE, duration = 0;
        for (int i = 1; i < MAX - MIN; ++i) {
            durationLogs[i] += durationLogs[i - 1];
            if (durationLogs[i] > maxUsage) {
                maxUsage = durationLogs[i];
                duration = i + MIN;
            }
        }

        System.out.printf("Max Usage %d is at time %d", maxUsage, duration);
    }

    private static void readFile(String dir, String fileName) throws IOException {
        Path path = Paths.get(dir, fileName);
        try (Stream<String> lines = Files.lines(path)) {
            lines.forEach(line -> {
                String[] words = line.split(" ");
                int start = Integer.parseInt(words[0]);
                int end = Integer.parseInt(words[1]);
                int usage = Integer.parseInt(words[2]);
                durationLogs[start - MIN] += usage;
            });
        }
    }
}

- rajat.shrivastava.aw September 23, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Here is a working solution in O(n * logn) time, and O(n) space.
The idea is to have one array sorted by start time and another one by end time. This allows us to track currently "open" logs.

We go through logs and increase the current memory usage when some interval is opening and decrease memory usage when some interval is closing:

public class MaximumMemoryUsageInLogs {

    public static void main(String[] args) {
        LogRecord[] logs = new LogRecord[]{new LogRecord("100207", "100209", 4), new LogRecord("100305", "100307", 5),
                new LogRecord("100207", "100208", 2), new LogRecord("111515", "121212", 1)};

        System.out.println(computeMaximumUsage(logs));

        logs = new LogRecord[]{new LogRecord("100207", "100211", 2), new LogRecord("100209", "100215", 5),
                new LogRecord("100214", "100218", 3), new LogRecord("100211", "100213", 6),
                new LogRecord("100208", "100209", 4)};

        System.out.println(computeMaximumUsage(logs));
    }

    private static String computeMaximumUsage(LogRecord[] logs) {
        LogRecord[] byStart = Arrays.copyOf(logs, logs.length);
        Arrays.sort(byStart, LogRecord.BY_START);

        LogRecord[] byEnd = Arrays.copyOf(logs, logs.length);
        Arrays.sort(byEnd, LogRecord.BY_END);

        int currentUsage = 0, maxUsage = 0;
        String maxTime = "";
        int i = 0, j = 0;

        while (i < byStart.length) {
            if (byStart[i].start.compareTo(byEnd[j].end) > 0) {
                currentUsage -= byEnd[j].usage;
                j++;
            } else {
                currentUsage += byStart[i].usage;
                if (currentUsage > maxUsage) {
                    maxUsage = currentUsage;
                    maxTime = byStart[i].start;
                }

                i++;
            }
        }

        return maxTime;
    }


    private static class LogRecord {
        private String start;
        private String end;
        private int usage;

        private static Comparator<LogRecord> BY_START = Comparator.comparing(l -> l.start);
        private static Comparator<LogRecord> BY_END = Comparator.comparing(l -> l.end);

        public LogRecord(String start, String end, int usage) {
            this.start = start;
            this.end = end;
            this.usage = usage;
        }

        @Override
        public String toString() {
            return "LogRecord{" +
                    "start='" + start + '\'' +
                    ", end='" + end + '\'' +
                    ", usage=" + usage +
                    '}';
        }
    }
}

- damluar October 20, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

public class LogMemory {
	
	public int calcMaxMemoryUsage(List<Log> ip){
		if(ip==null || ip.size()==0)
			return 0;
		if(ip.size() == 1)
			return ip.get(0).u;
		Collections.sort(ip, new Comparator<Log>(){
			public int compare(Log l1,Log l2){
				return l1.s-l2.s;
			}
		});
		
		Map<Integer,ArrayList<Integer>> map = new HashMap<>();
		ArrayList<Integer> temp = new ArrayList<Integer>();
		temp.add(ip.get(0).u);
		map.put(ip.get(0).e,temp);
		int curUsage = ip.get(0).u; int maxUsage = 0;
		for(int i=1;i<ip.size();i++){
			Log cur = ip.get(i);
			curUsage += cur.u;
			List<ArrayList<Integer>> less = getEndTimeLessThanCur(cur.s,map);
			for(List<Integer> curList : less){
				for(int usage : curList){
					curUsage-=usage;
				}
			}
			if(map.containsKey(cur.e)){
				map.get(cur.e).add(cur.u);
			}else{
				temp = new ArrayList<Integer>();
				temp.add(cur.u);
				map.put(cur.e,temp);
			}
			maxUsage = Math.max(curUsage,maxUsage);
		}
		
		return maxUsage;
	}
	
	public List<ArrayList<Integer>> getEndTimeLessThanCur(int cur,Map<Integer,ArrayList<Integer>> map){
		List<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
		for(int end : map.keySet()){
			if(end < cur)
				result.add(map.get(end));
		}
		
		return result;
	}
	
	public static void main(String[] args){
		Log l1 = new Log(0,5,10);
		Log l2 = new Log(1,3,5);
		Log l3 = new Log(2,3,5);
		ArrayList<Log> ip = new ArrayList<Log>();
		ip.add(l1); ip.add(l2); ip.add(l3);
		LogMemory l = new LogMemory();
		System.out.println(l.calcMaxMemoryUsage(ip));
	}
	

}

class Log{
	int s,e,u;
	public Log(int start,int end, int usage){
		s=start; e= end; u = usage;
	}
	public String toString(){
		return String.valueOf(s) + ","+String.valueOf(e)+ "," + String.valueOf(u);
	}
}

- Swaraj October 08, 2016 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

public class LogMemory {
	
	public int calcMaxMemoryUsage(List<Log> ip){
		if(ip==null || ip.size()==0)
			return 0;
		if(ip.size() == 1)
			return ip.get(0).u;
		Collections.sort(ip, new Comparator<Log>(){
			public int compare(Log l1,Log l2){
				return l1.s-l2.s;
			}
		});
		
		Map<Integer,ArrayList<Integer>> map = new HashMap<>();
		ArrayList<Integer> temp = new ArrayList<Integer>();
		temp.add(ip.get(0).u);
		map.put(ip.get(0).e,temp);
		int curUsage = ip.get(0).u; int maxUsage = 0;
		for(int i=1;i<ip.size();i++){
			Log cur = ip.get(i);
			curUsage += cur.u;
			List<ArrayList<Integer>> less = getEndTimeLessThanCur(cur.s,map);
			for(List<Integer> curList : less){
				for(int usage : curList){
					curUsage-=usage;
				}
			}
			if(map.containsKey(cur.e)){
				map.get(cur.e).add(cur.u);
			}else{
				temp = new ArrayList<Integer>();
				temp.add(cur.u);
				map.put(cur.e,temp);
			}
			maxUsage = Math.max(curUsage,maxUsage);
		}
		
		return maxUsage;
	}
	
	public List<ArrayList<Integer>> getEndTimeLessThanCur(int cur,Map<Integer,ArrayList<Integer>> map){
		List<ArrayList<Integer>> result = new ArrayList<ArrayList<Integer>>();
		for(int end : map.keySet()){
			if(end < cur)
				result.add(map.get(end));
		}
		
		return result;
	}
	
	public static void main(String[] args){
		Log l1 = new Log(0,5,10);
		Log l2 = new Log(1,3,5);
		Log l3 = new Log(2,3,5);
		ArrayList<Log> ip = new ArrayList<Log>();
		ip.add(l1); ip.add(l2); ip.add(l3);
		LogMemory l = new LogMemory();
		System.out.println(l.calcMaxMemoryUsage(ip));
	}
	

}

class Log{
	int s,e,u;
	public Log(int start,int end, int usage){
		s=start; e= end; u = usage;
	}
	public String toString(){
		return String.valueOf(s) + ","+String.valueOf(e)+ "," + String.valueOf(u);
	}
}

- Swaraj October 08, 2016 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 1 vote

My Solution would be to create three classes,
MonthClass, DayClass, HoursClass,
in a hierarchical order.

We can instantiate an object for all the months, days and hours touched by the ranges provided in String input.

like:
[Root]
__l__
| |
[Jan] [Feb] ....
__|__ __|__
|
[Day1]....
|
[Hour1]...

And update the ranges for the hours.

Then a simple DFS can give us the Hour with the highest value!

P.S: Please feel free to slam on, if the sol. doent make sense.

- thisisvasanths September 25, 2015 | 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