Google Interview Question for Software Engineer / Developers


Country: United States
Interview Type: In-Person




Comment hidden because of low score. Click to expand.
11
of 17 vote

DFS

public boolean canArrange(int[] servers, int[] tasks) {
        boolean[] used = new boolean[tasks.length];
        return canArrangeRecursive(servers, tasks, used);
    }

    public boolean canArrangeRecursive(int[] servers, int[] tasks, boolean[] used) {
        boolean allUsed = true;
        for (boolean b : used) {
            allUsed &=b;
        }
        if (allUsed){
            return true;
        }
        for (int i = 0; i < tasks.length; i++) {
            if (!used[i]) {
                used[i] = true;
                for (int j = 0; j < servers.length; j++) {
                    if (servers[j] >= tasks[i]) {
                        servers[j] = servers[j] - tasks[i];
                        if(canArrangeRecursive(servers, tasks, used)){
                            return true;
                        }
                        servers[j] = servers[j] + tasks[i];
                    }
                }
                used[i] = false;
            }
        }
        return false;

}

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

I think this is a reasonable solution. Brilliant!

- Lisa August 06, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

What if sort the server and tasks first to reduce the run time?

- xlshi August 11, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Yep sorting is good idea to omit dfs checks on the same sized tasks (and servers)

- driv3r August 12, 2014 | Flag
Comment hidden because of low score. Click to expand.
6
of 6 votes

There are two loops for each level of recursion, which means O(n^2 * (n-1)^2 * (n-2)^2 ....), which means O(n ^ n)? Am I wrong?

- zprogd August 14, 2014 | Flag
Comment hidden because of low score. Click to expand.
-1
of 3 votes

Recursive solution is not preferred, they are rarely used in production code.

Greedy soln:
1. Use two max heaps, one for storing all remaining capacities of servers and one for storing tasks.
2. Pop max. task from tasks' heap and subtract max. task length from the max. server. If remaining capacity of server becomes zero, delete the element.
Max heapify both heaps.
3. Do this untill the tasks heap is finished or max. task length is greater than max. server capacity.

Ofcourse, you have to prove this greedy algo. is optimal.

Complexity: O(nlogn + mlogm)

- Poison September 04, 2014 | Flag
Comment hidden because of low score. Click to expand.
-2
of 2 votes

Server capacity limits: 1, 3
Task capacity needs: 4

In this case, the above code returns 'true' that is not expected behavior.

servers[j] >= tasks[i] needs be changed into '>'?

- soodongStudying September 14, 2014 | Flag
Comment hidden because of low score. Click to expand.
4
of 4 votes

The greedy solution proposed above fails for e.g:
Servers: 8,24
Tasks: 6,6,6,6,8.
It would assign 8 to 24,then assign two more sixes to 24. It would then be left with two tasks of size 6 and a server of cap 8, so it would return false.
Obviously you can solve the above problem by assigning all 6s to server 24, and 8 to server 8.

- Lenny September 19, 2014 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

Just adding a minor comment that this problem is NP-complete, i.e, let's assume you have a general case with N servers and M tasks and let the capacity of all servers be the same. Then, the question whether or not you can fit all tasks inside servers is equivalent to packing M stones in N bins, i.e., you are answering a general instance of the bin-packing problem. If you can make it work with N, then you keep reducing N until you find the smallest number of servers.

That being said, the recursive DFS, i.e., backtracking is the best bet as far as I can tell.

- Ehsan October 23, 2014 | Flag
Comment hidden because of low score. Click to expand.
4
of 4 votes

What is the point of using 2 loops? each task can be assigned to one of the eight servers so total complexity is 8^8. So in each step of the dfs, you get 8 choices of server for each task. A simple 15 line code would do :)

public boolean dfs(int pos, int[] tasks, int[] servers) {
		boolean result = false;
		if (pos >= tasks.length)
			return true;
		for (int i = 0; i < servers.length; i++) {
			if (servers[i] - tasks[pos] >= 0) {
				servers[i] -= tasks[pos];
				result |= dfs(pos + 1, tasks, servers);
				servers[i] += tasks[pos];
			}
		}
		return result;
	}

- renegade403 January 12, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

If you do it this way it will be not 8^8 but 8^tasks.length.

- 0xF4 January 12, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Can anybody tell me what is wrong with my code? Thanks!

bool taskToserver(int server[10], int task[10], bool used[10], int n, int task_size, int server_size){

	bool allUsed = true;
	for(int i = 0; i < task_size; i ++){
		if(used[i]== false){
			allUsed = used[i];
			break;
		}


	}
	if(allUsed) return true;
	if(n == task_size) return false;
	for(int i = 0; i < server_size; i ++){
		if(!used[n] && task[n] < server[i]){
			used[n] = true;
			server[i] -= task[n];
			if(taskToserver(server, task, used, n + 1, task_size, server_size)){
				return true;

			}
			server += task[n];
			used[n] = false;
		}
	}
	return false;
}

- Q September 11, 2015 | Flag
Comment hidden because of low score. Click to expand.
3
of 3 vote

Looks like a Max-Flow problem to me.
Let J be the group of jobs and W be the list of work servers.

1. Create a graph so that each job is a node and each worker is a node.
2. Create an Edge between each job node and each server node iff that worker's capacity is less than or equal to the task's requirements, set the value of each edge to be the job requirements.
3. Add a node S, and an edge from S to each task node in T and set the value to infinity (or Integer.MAX_VALUE)..
4. Add a node T, and an edge from each worker in W to T. set the value of each edge to be the capacity of the worker.
5. Run a max flow algorithm (e.g. Ford Fulkerson) and return "True" iff the max flow of the graph equals the sum of all the jobs in J.

- E.B. August 05, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
1
of 1 vote

This will not work because in max-flow problem you could divide the flow from a job node to multiple worker nodes, but this is not allowed in the problem. You cannot have half the job running on one server and other half on other server.

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

Flow network is really a great idea though your solution actually doesn't suits for the problem as gimli said above.
I think flow network could work for this problem with some modify on your method

- fmars October 13, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Nice idea, but I think we need to
add T and t_sum nodes and edge (T,t_sum) with w(T,t_tag) = sum of all tasks needs
add edges( t_i, t_sum) with w(t_i, t_sum) = need of task i
add edges (S, s_j) with w(S, s_j) = capacity of server j
and add edges(t_i, s_j) if capacity of server j is >= need of task i

- marina.gupshpun May 29, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

^^add edge (t_sum, T)

- marina.gupshpun May 29, 2015 | Flag
Comment hidden because of low score. Click to expand.
2
of 4 vote

#include<stdio.h>
#include<conio.h>

int assign(int serverCapacities[],int tasks[],int no_servers,int tasks_start,int tasks_end)
{
	int i,j,k;
	if( tasks_end < tasks_start)
		return 1;
	
	for( i=0; i<no_servers; i++)
		if( tasks[tasks_start] <= serverCapacities[i] )
		{
			//if current server is capable of handling the cuurent task, then assign it
			//Reduce the capacity of current server
			serverCapacities[i] -= tasks[tasks_start];
			
			
			if(assign(serverCapacities,tasks,no_servers,tasks_start+1,tasks_end))
				return 1;
			//backtracking
			serverCapacities[i] += tasks[tasks_start];
		}
		
	return 0;
	
}
int main()
{
	int serverCapacities[]={8,16,8,32};
	int tasks[]={18,4,8,4,6,6,8,8};
	int no_servers;
	int no_tasks;
	no_servers = sizeof(serverCapacities)/sizeof(int);
	no_tasks = sizeof(tasks)/sizeof(int);
	if ( assign(serverCapacities,tasks,no_servers,0,no_tasks-1) )
	{
		printf("True");
	}
	else
	{
		printf("False");
	}
	getch();
}

- Shankar August 07, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Very nice solution. Similar to driv3r's but doesn't need the auxiliary array to keep track of tasks that have been already allocated. In addition, it doesn't loop through the tasks, instead, each recursive call gets one task less to handle. This reduces the total number of calls tremendously.

- cassio.neri August 16, 2014 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

class ServerCapacity:
        def __init__(self, list_capacity):
                self.list_capacity = sorted(list_capacity, reverse=True)
                self.list_server = [] * len(list_capacity)
                self.answer = False
        
        def solution(self, list_job):
                self.list_job = sorted(list_job)
                self.recursive_walk(self.list_capacity, self.list_job)
                return self.answer

        def recursive_walk(self, list_capacity, list_job):
                #print 'recursive_walk, cap: ', list_capacity
                #print 'recursive_walk, job: ', list_job

                # if job list is empty, done here
                if not len(list_job):
                        self.answer = True
                        return True

                # pop up the biggest job
                job = list_job.pop()

                # check if any server can take this job
                has_server = False
                for i, capacity in enumerate(list_capacity): 
                        if capacity >= job:
                                list_capacity[i] -= job
                                has_server = True

                                #
                                # if this assign doesn't work, return capacity, check 
                                # next server
                                #
                                if not self.recursive_walk(list_capacity, list_job):
                                        list_capacity[i] += job
                                        has_server = False

                # if no server can handle this job, return False
                if not has_server:
                        return False

if __name__ == "__main__":
        list_cap = [[1,3], [4,1], [8,16,8,32],       [8,6,2]]
        list_job = [[  4], [  4], [18,4,8,4,6,6,8,8],[5,4,4,2,1]]

        for cap, job in zip(list_cap, list_job):
                s = ServerCapacity(cap)
                print 'Solution :', s.solution(job)

- Solomon Yang August 04, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

I think this is the correct solution, but can you also explain this. I am not very familiar with this programming language, but seems like you are filling the server with tasks going in descending order of capacity. If you fail to fit a task at any stage, you back track and try next server until you either find a solution or run out of all servers to try.

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

@Solomon Yang
In point of view giving a code directly for a problem is not going to be so much worthy , please give your algorithm and let the other code it. It will also give a better understanding of solution in quick time . Btw thanx for solution.

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

This is a basic recursive algorithm. It will definitely work.
What the code does is
1. Assigns the largest job to a server(i)
2. Recurse on the remaining set of jobs and new server capacities(modified server capacity i)
3. If the recursive problem can be solved, we get a solution for the problem else assigns the ith job to another server

Complexity
Each job can be assigned to any of the servers
So it looks like O(#servers^#jobs)

- pratikkumarshanu August 06, 2014 | Flag
Comment hidden because of low score. Click to expand.
1
of 3 vote

first sort the task capacity needs in descending order and try to find best fit for each task capacity needs.
where best fit is min of capacity greater than equal to the task capacity need
eg- capacity limits- 8,16,8,32
after sorting task capacity needs - 18,8,8,8,6,6,4,4
1)best fit for 18 is min no in capacity limit array which is greater than equal to 18, which is 32 after this pass
capacity needs - 8,8,8,6,6,4,4
capacity limits-8,16,8,14

2) best fit for 8 is 8 after this pass
capacity needs -8,8,6,6,4,4
capacity limits-0,16,8,14

3)best fit for 8 is 8
capacity needs -8,6,6,4,4
capacity limits-0,16,0,14

4)best fit for 8 is 14
capacity needs -6,6,4,4
capacity limits-0,16,0,6

5)best fit for 6 is 6
capacity needs -6,4,4
capacity limits-0,16,0,0

6)best fit for 6 is 16
capacity needs -4,4
capacity limits-0,10,0,0

7)best fit for 4 is 10
capacity needs -4
capacity limits-0,6,0,0

8)best fit for 4 is 6
capacity needs -
capacity limits-0,2,0,0

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

Unfortunately this doesn't work. Consider needs = (5, 3, 3, 2) and limits = (7, 6). A solution is 7 = 5 + 2 and 6 = 3 + 3. However, running your algo on this data yields

1) Best fit for 5 is 6:
needs = (3, 3, 2)
limits = (7, 1)

2) Best fit for 3 is 7:
needs = (3, 2)
limits = (4, 1)

3) Best fit for 3 is 4:
needs = (2)
limits = (1, 1)

and then it stops failling to allocate a server for task 2.

- cassio.neri August 16, 2014 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

Mode the problem as a giftbox problem, i.e., put several gifts in different sizes into boxes in different sizes. The strategy is try to put the largest gift into the lagest box and repeat the process until all gifts are boxed. If at a certain point the process fails, try the second largest box, then the third largest and so forth.

Implemented in scala is a brute force solution (NP complete, worst case O(n^3), n be the number of gifts), but since it can return early, the algorithm is quite efficient (best case O(n)). Note sorting the boxes can be further optimized with a simple insertion at the right place (linear).

class GiftBox {
	def fit(boxes: Seq[Int], gifts: Seq[Int]) : Boolean = {
		var g = gifts.last
		var b = boxes.last 
		println(s"Checking $boxes for $gifts")
		
		if (gifts.length<=1) return boxes.toList.exists(_>=g)

		for (i<- boxes.size-1 to 0 by -1 if boxes(i)>=g) {
			b = boxes(i)
			val bb = boxes.take(i)++boxes.drop(i+1):+(b-g)
			if (fit(bb.sorted, gifts.init)) return true
		}
		return false
	}
}

object GiftBox extends App {
	val giftBox = new GiftBox
	
	println(giftBox.fit(Seq(8, 16, 8, 32).sorted, Seq(18, 4, 8, 4, 6, 6, 8, 8).sorted))
	println(giftBox.fit(Seq(8,6,2).sorted, Seq(5,4,4,2,1).sorted))
	println(giftBox.fit(Seq(1,3).sorted, Seq(4).sorted))
	
}

The three test cases gives true, true, false

Checking List(8, 8, 16, 32) for List(4, 4, 6, 6, 8, 8, 8, 18)
Checking List(8, 8, 14, 16) for List(4, 4, 6, 6, 8, 8, 8)
Checking List(8, 8, 8, 14) for List(4, 4, 6, 6, 8, 8)
Checking List(6, 8, 8, 8) for List(4, 4, 6, 6, 8)
Checking List(0, 6, 8, 8) for List(4, 4, 6, 6)
Checking List(0, 2, 6, 8) for List(4, 4, 6)
Checking List(0, 2, 2, 6) for List(4, 4)
Checking List(0, 2, 2, 2) for List(4)
Checking List(0, 0, 2, 8) for List(4, 4)
Checking List(0, 0, 2, 4) for List(4)
true
Checking List(2, 6, 8) for List(1, 2, 4, 4, 5)
Checking List(2, 3, 6) for List(1, 2, 4, 4)
Checking List(2, 2, 3) for List(1, 2, 4)
Checking List(1, 2, 8) for List(1, 2, 4, 4)
Checking List(1, 2, 4) for List(1, 2, 4)
Checking List(0, 1, 2) for List(1, 2)
Checking List(0, 0, 1) for List(1)
true
Checking List(1, 3) for List(4)
false

- sabz August 06, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

I'm not familir with scala but you said that "The strategy is try to put the largest gift into the lagest box...". If this is what your code is doing, then it doesn't work. Consider servers/boxes = (6, 5) and tasks/gifts = (5, 3, 3). Unless I'm missing something, your strategy puts gift 5 into box 6, gift 3 into box 5 and there's no room for the other gift 3. However, we could put gift 5 into box 5 and the two gifts 3 into box 6.

- cassio.neri August 16, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Cassio,
The algo also says "If at a certain point the process fails, try the second largest box, then the third largest and so forth". This is an essential part of the algorithm that handles your case. Though you are not familiar with scala, you can read the trace of the program execution to find the following case:
Checking List(0, 2, 6, 8) for List(4, 4, 6)
Checking List(0, 2, 2, 6) for List(4, 4)
Checking List(0, 2, 2, 2) for List(4)
Checking List(0, 0, 2, 8) for List(4, 4)
which first tried to put 6 into 8 and after failure put 6 into 6 leading to a success.

Would you think twice before you vote the solution down?

- sabz August 19, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

So, I was indeed missing something. I might be wrong again but it seems to me that your solution is similar to Shankar's (which I like very much) with added heuristics (trying to put big gifts in big giftbox first) that may speed up the algo.

I don't remember having voted your solution down. I normally don't vote down a solution that I don't understand (and I didn't understand yours). But, if I did, then I apologise. I have voted it up now (I think the heuristics is a good idea).

- cassio.neri August 19, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

I can think of the following algorithm at high level, correct me if i am wrong

1.Check if we have exact fit available for a task
2.If not find the possible fit for that task
3.Get the best possible fit if we have multiple possible fits available
4.Best possible fit can be defined as the exact fit of 2 or more available tasks combined

- NC August 05, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

Basically, one way is to solve using recursive backtracking with no memoization.
Given a list of jobs L1 with service times S_i, and a list of servers L2 with with capacities C_i, we try each job on all servers one by one until the list L1 is traversed. Its like Depth First Search with backtracking (in case we don't find the solution along the path).
An improvization would/could be memoization instead of backtracking.
Say, we order the list L1 in descending order of service rates.
The state I would memoize is.
S[Sorted List of remaining capacities in L2, i] => The current state of List L2 after processing the 1st i elements of L1
S[Sorted List of remaining capacities in L2, i] = {-1, 0, 1}
-1 means not yet memoized
0 means not possible
1 means possible

------------------------------------------------------------------------------------------------
The important part is that i am storing List L2 after sorting it, because all servers are identical. (so that we don't have to recompute for the same list in different order)

- raghavsagar92 August 05, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

This question is form of bin-packing algorithm. Will post the solution soon.

- Victor August 07, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

yes, this is a bin sort problem. First, sort the tasks in the descending order. Then assign the tasks to each bin as long as it can fit it.

here is the solution:
bool bin_packing(int* tasks, int nt, int* workers, int nw) {
quick_sort_kernel(tasks, 0, nt-1);
bool setted_tasks[nt];
for(int i = 0; i < nt; i++) {
int cur_task = tasks[i];
setted_tasks[i] = false;
printf("task:%d ", cur_task);
for(int j = 0; j < nw; j++) printf("%d ", workers[j]);
printf("\n");
for(int j = 0; j < nw; j++) {
if(workers[j]-cur_task >= 0) {
workers[j] = workers[j]-cur_task;
setted_tasks[i] = true;
break;
}
}
}
for(int i = 0; i < nt; i++) {
if(!setted_tasks[i]) return false;
}
return true;
}

- Linnan August 07, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

bool CanScheduleTasks(std::vector<int> capacities
                          , std::vector<int> tasks)
    {
        bool ret = false;
        
        if (tasks.size() == 0)
        {
            ret = true;
        }
        else if (capacities.size() == 0)
        {
            ret = false;
        }
        else
        {
            for (int i = 0; i < tasks.size(); i++)
            {
                for (int j = 0; j < capacities.size(); j++)
                {
                    if (tasks[i] <= capacities[j])
                    {
                        std::vector<int> tempCapacities(capacities.size());
                        std::copy(capacities.begin(), capacities.end(), tempCapacities.begin());
                        tempCapacities[j] -= tasks[i];

                        std::vector<int> tempTasks(tasks.size());
                        std::copy(tasks.begin(), tasks.end(), tempTasks.begin());
                        tempTasks.erase(tempTasks.begin()+i);
                        
                        ret = ret || CanScheduleTasks(tempCapacities, tempTasks);
                    }
                }
            }
        }
        
        return ret;
    }

- Anonymous August 11, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

isn't this problem the Bin Packing problem, and therefore NP-Hard?

- Anonymous August 14, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 2 vote

O(m*n) in worst case. Enjoy.

bool canArrange(int* servers, int servers_len, int* tasks, int tasks_len) {
  if (tasks_len == 0)
    return true;
  for (int i = 0; i < servers_len; i++) {
    if (servers[i] >= tasks[tasks_len - 1]) {
      servers[i] -= tasks[task_len - 1];
      if (canArrange(servers, servers_len, tasks, tasks_len - 1))
        return true;
      servers[i] += tasks[task_len - 1];
    }
  }
  return false;
}

- zprogd August 14, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
1
of 1 vote

@zprogd, Hi, Could you explain why this is time complexity = O(m * n)? I think this is O(m^n), m is the number of servers and n is the number of tasks. Think about this: Since there is n tasks, so the max depth of the recursion is n, and each level of recursion we have a for-loop, that means each level is O(m), so the totally time complexity = O(m^n), I am not sure my analysis, any wrong, pleas point out.

- lzninusproject August 24, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Complexity of this solution is wrong but the code look okay so voting +1.

- MIG February 07, 2015 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

1) Let L be an array of tasks in some order.
2) The first server takes as many adjacent tasks as it can from the start of L. From what is left, the second server takes as many adjacent tasks as it can, and so on. If all tasks are taken then we're done and return true.
3) Otherwise, change L to another permutation of tasks and go back to step 2, unless all permutations have been tried, in which case, return false.

Here is C++ code. Notice that can_allocate uses 'std::next_permutation' which generates permutations in lexicographical order. To ensure that all permutations are generated, 'tasks' must be initialized in increasing order.

typedef std::vector<unsigned> array;

bool can_allocate_in_order(array const& tasks, array const& servers) {
  
  auto need = tasks.begin();
  
  for (unsigned limit : servers) {
    
    while (limit >= *need) {
      
      limit -= *need;
      ++need;
      
      if (need == tasks.end())
        return true;
    }
  }
  return false;
}

// Assume tasks is in increasing order.
bool can_allocate(array& tasks, array const& servers) {
  do {
    if (can_allocate_in_order(tasks, servers))
      return true;
  } while (std::next_permutation(tasks.begin(), tasks.end()));
  return false;
}

Let n be the number of tasks and m be the number of servers. We have:

a) 'std::next permutation' has O(n) complexity;
b) 'can_allocate_in_order' is ran at most n! times;
c) 'can_allocate_in_order' has complexity O(n + m).

Since n = 8, 'can_allocate_in_order' can be called up to 8! = 40,320 times. This is arguably a big number however:

a) 'std::next_permutation' takes into consideration repetitions less calls are made. For instance, for tasks = {4, 4, 6, 6, 8, 8, 8, 18}, 4 is repeated 2 times, 6 is repeated 2 times and 8 is repeated 3 times. The number of calls is reduced to, at most, 8! / (2!*2!*3!) = 1,680.

b) Even when this maximum is achieved (e.g., when tasks = {1, 2, 3, 4, 5, 6, 7, 33}) the C++ code above takes a fraction of a second to run in my computer.

c) In contrast, driv3r's algorithm (ported to C++), for tasks = {1, 2, 3, 4, 5, 6, 7, 33} calls 'canArrangeRecursive' 37,369,133 times and takes a few of seconds to run.

The implementation can be easily modified to use Heap's algorithm (which has nothing to do with the homonymous data structure) to generate each permutation in O(1) and it doesn't make any assumption on 'tasks' initial order. The price to pay is that Heap's algorithm doesn't take profit of repetitions.

- cassio.neri August 16, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

Please, don't +1 this solution (mine). Consider, Shankar's instead.

- cassio.neri August 16, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

The algo also saids "If at a certain point the process fails, try the second largest box, then the third largest and so forth". In your example the code will roll back to try gift 5 in box 5.

- sabz August 18, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

The algo also saids "If at a certain point the process fails, try the second largest box, then the third largest and so forth". In your example the code will roll back to try gift 5 in box 5.

- sabz August 18, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

#include <iostream>
#include <vector>

void printvec(std::vector<int> vec) {
  std::vector<int>::size_type vec_sz = vec.size();
  for (int i=0; i < vec_sz; i++) {
    std::cout << vec[i] << " ";
  } std::cout << std::endl;
}

int main() {
  std::cout << "Server capacity limits: ";
  int user_input;
  std::vector<int> server_cap;

  while (std::cin >> user_input) {
    if (user_input == -1)
      break;
    server_cap.push_back(user_input);
  }

  std::vector<int> task_needs;

  std::cout << "Task capacity needs: ";

  while (std::cin >> user_input) {
    task_needs.push_back(user_input);
  }

  //Sort our server and task vectors
  std::sort(server_cap.begin(), server_cap.end());
  std::sort(task_needs.begin(), task_needs.end());

  typedef std::vector<int>::const_iterator iter;
  typedef std::vector<int>::size_type vec_sz;

  iter task_vec_it = task_needs.begin();
  iter task_vec_it_end = task_needs.end();

  vec_sz task_size = task_needs.size();
  vec_sz server_size = server_cap.size();

  int task_largest;
  int server_largest;

  for (; task_vec_it != task_vec_it_end+1; task_vec_it++) {

    std::cout << "task_needs size: " << task_size << std::endl;
    printvec(server_cap);
    printvec(task_needs);

    if (task_needs.empty()) {
      std::cout << "All tasks handled!" << std::endl;
      return 0;
    }

    //Get the largest value in task_needs & server_cap
    task_largest = *max_element(task_needs.begin(), task_needs.end());
    server_largest = *max_element(server_cap.begin(), server_cap.end());

    if (server_largest < task_largest) {
      std::cout << "No server's can handle your request!" << std::endl;
      return -1;
    }

    //Subtract largest value of tasks from largest value of vectors
    //and store it in server vector
    server_cap[server_size-1] -= task_needs[task_size-1];
    task_needs.pop_back();

    //Re-sort vectors
    std::sort(server_cap.begin(), server_cap.end());
    std::sort(task_needs.begin(), task_needs.end());

    //Get new size of task_needs
    task_size = task_needs.size();
  }

  return 0;
}

- Verbose_But_Clear August 21, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

This is incorrect. You do not break up the jobs 'nicely.' The first example does not work. Consider a better way to break up the jobs. Also sorting so many times is not very efficient for larger numbers.

- Verbose_But_Clear_And_Incorrect August 21, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 2 vote

{{def isSchedulable(limits,requires):
if len(requires)==0:
return True
if len(limits)==0:
return False
limits.sort()
limits=limits[::-1]
requires.sort()
requires=requires[::-1]
if requires[0]>limits[0]:
return False
else:
limits[0]=limits[0]-requires[0]
while requires[-1]<=limits[0]:
limits[0]=limits[0]-requires[-1]
requires.pop()
if limits[0]==0:
limits.pop(0)
requires.pop(0)
return isSchedulable(limits,requires)}}

- A greedy approach works August 22, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

No need of DP, greedy algorithm works:

def isSchedulable(limits,requires):
    if len(requires)==0:
        return True
    if len(limits)==0:
        return False
    limits.sort()
    limits=limits[::-1]
    requires.sort()
    requires=requires[::-1]
    if requires[0]>limits[0]:
        return False
    else:
        limits[0]=limits[0]-requires[0]
        while requires[-1]<=limits[0]:
            limits[0]=limits[0]-requires[-1]
            requires.pop()
        if limits[0]==0:
            limits.pop(0)
        requires.pop(0)
        return isSchedulable(limits,requires)

- robotonyszu August 22, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

I have got a solution. Correct me if I am wrong conceptually.
Pick the boxes one by one.
For each of the boxes, apply the 0/1 knapsack with the slight modification that if there are multiple ways to fill the box, then choose the way where the weight of the heaviest box is maximum at each step.

- neil1422 August 24, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
1
of 1 vote

This is what I was thinking. The key thing to realise is that if we 'stuff' each server independently as efficiently as possible (i.e. as little unused cap as possible), we can reduce the problem by 1 server and an arbitrary number of tasks. We can continue from there as before. Now, 'stuffing' each server as effectively as possible is done by the 0/1 knapsack problem as you said. This solution seems correct at least for two servers, and might be generalised to arbitrarily many servers. It's certainly a nice thing to mention in an interview, even if it turns out to not be correct in the end, you'd get kudos for trying a non-brute-force solution.

- Lenny September 19, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

import java.util.ArrayList;
import java.util.List;


class Scenario {
	
	int[] remainingValues;
	public Scenario(Scenario scenario) {
		int[] toCopy = scenario.getRemainingValues();
		remainingValues = new int[toCopy.length];
		
		for (int i = 0; i < toCopy.length; i++) {
			this.remainingValues[i] = toCopy[i];
		}
	}

	public Scenario(int[] values) {
		remainingValues = new int[values.length];
		for (int i = 0; i < values.length; i++) {
			this.remainingValues[i] = values[i];
		}
	}

	public int getRemainingValueAt(int server) {
		return remainingValues[server];
	}

	public int[] getRemainingValues() {
		return remainingValues;
	}

	public void decrementRemainingValue(int index, int byValue) {
		this.remainingValues[index] -= byValue;
	}
}
  
class DoesItFit {
	
	public static boolean findIfThingsFit(int[] capacity, int[] proceses) {
		Scenario initialScenario = new Scenario(capacity);
		List<Scenario> scenariosEncountered = new ArrayList<Scenario>();
		scenariosEncountered.add(initialScenario);

		for (int i = 0; i < proceses.length; i++) {
			List<Scenario> newScenarios = new ArrayList<Scenario>();
			for (int j = 0; j < capacity.length; j++) {
				for (Scenario scenario : scenariosEncountered) {
					if (scenario.getRemainingValueAt(j) >= proceses[i]) {
						Scenario newScenario = new Scenario(scenario);
						newScenario.decrementRemainingValue(j, proceses[i]);
						newScenarios.add(newScenario);
					}
				}
				
			}
			scenariosEncountered.clear();
			scenariosEncountered.addAll(newScenarios);
		}
		return scenariosEncountered.size() > 0;
	}
	public static void main (String argv[]){
		System.out.println(findIfThingsFit(new int[]{8, 16, 8, 32}, new int[]{18, 4, 8, 4, 6, 6, 8, 8}));
		System.out.println(findIfThingsFit(new int[]{7,6}, new int[]{5, 3, 3, 2}));
		
	}
}

- Dibzee August 26, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

1. Read the input
2. Put both ServerCapacity and Tasks in separate Integer ArrayList s.
3. Sort both ArraList s in Desc order.
4. For the Biggest task, Try to fit in biggest server.
5. If Task is Bigger Than Capacity then there is no point in moving ahead.

public class ServerCapacity {

    public static void main(String[] args) throws InterruptedException {
        Scanner c = new Scanner(System.in);

        System.out.println("Enter Servers capacity limits: ");
        String serCapLim = "8, 16, 8, 32"; //c.nextLine();
        serCapLim = "1,3";
        System.out.println("Enter Tasks capacity Need: ");
        String taskCapNeed = "18, 4, 8, 4, 6, 6, 8, 8"; //c.nextLine();
        taskCapNeed="4";

        String[] splits = serCapLim.split(",");
        ArrayList<Integer> serCaps = new ArrayList(splits.length);
        for (int i = 0; i < splits.length; i++) {
            serCaps.add(Integer.parseInt(splits[i].trim()));
        }

        splits = taskCapNeed.split(",");
        ArrayList<Integer> taskNeeds = new ArrayList(splits.length);
        for (int i = 0; i < splits.length; i++) {
            taskNeeds.add(Integer.parseInt(splits[i].trim()));
        }

        try {
            boolean flag = checkCapacity(serCaps, taskNeeds);
            System.out.println("flag:" + flag);
        } catch (Exception e) {
        }
    }

    public static boolean checkCapacity(ArrayList<Integer> serCaps, ArrayList<Integer> taskNeeds) throws Exception {
        //check if the capacity is in Limits
        if (serCaps.size() > 8 | taskNeeds.size() > 8) {
            throw new Exception("Either task or servers are not in limit");
        }

        //first sort those lists in desc order
        Collections.sort(taskNeeds, Collections.reverseOrder());
        
        //if the find returns true then 
        return findTaskAssignment(taskNeeds, serCaps);
    }
    
    /**
     * Finds the assignment of task on server and reiterates for remaining.
     * Find the assignment for the biggest Job first on the biggest capacity server.
     * @param taskNeeds
     * @param serCaps
     * @return 
     */
    private static boolean findTaskAssignment(ArrayList<Integer> taskNeeds, ArrayList<Integer> serCaps) {
        if(taskNeeds.size()==0)
            return true;        
        int task = taskNeeds.get(0);
        Collections.sort(serCaps, Collections.reverseOrder());
        System.out.println("task to be assigned:" + task);
        System.out.println("server Caps remaining:" + serCaps);
        
        boolean flag = false;
//        for(int i=0; i<serCaps.size(); i++){
            int i=0;
            int cap=serCaps.get(i);
            //if task is bigger than cap then there is no point
            if (task > cap) {
                return false;
            } //if task is same as cap then assign
            else if (task == cap) {
                serCaps.remove(Integer.valueOf(task));
//                return true;
                taskNeeds.remove(0);
            } //else if the same size is ther
            else if(serCaps.contains(task)){
                //if we just enter task then it considers as index so we have to cast to Integer object
                serCaps.remove(Integer.valueOf(task)); 
//                return true;
                taskNeeds.remove(0);
            }
            //else deduct that task from the cap
            else {
                serCaps.set(i, cap-task);                
//                return true;
                taskNeeds.remove(0);
            }
//        }
        System.out.println("Next iteration");
        return findTaskAssignment(taskNeeds, serCaps);
    }
}

- Satyen August 26, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

1. Get input Capacity and tasks in separate ArrayList s
2. Sort both ArrayList s in Desc order.
3. For the Highest task check the Highest available Server capacity.
3. If the task is bigger than any server capacity then there is no point in moving ahead.
4. If the same capacity as task is found then remove both task and capacity from respective ArrayList s.
5. If the Task is smalled than the Capacity then deduct from capacity
6. Reiterate till you find servers for all Tasks.

- Satyen August 26, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

1. Get input Capacity and tasks in separate ArrayList s
2. Sort both ArrayList s in Desc order.
3. For the Highest task check the Highest available Server capacity.
3. If the task is bigger than any server capacity then there is no point in moving ahead.
4. If the same capacity as task is found then remove both task and capacity from respective ArrayList s.
5. If the Task is smalled than the Capacity then deduct from capacity
6. Reiterate till you find servers for all Tasks.

and the code

- Satyen August 26, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

1. Get input Capacity and tasks in separate ArrayList s
2. Sort both ArrayList s in Desc order.
3. For the Highest task check the Highest available Server capacity.
3. If the task is bigger than any server capacity then there is no point in moving ahead.
4. If the same capacity as task is found then remove both task and capacity from respective ArrayList s.
5. If the Task is smalled than the Capacity then deduct from capacity
6. Reiterate till you find servers for all Tasks.

and the code

- Satyen August 26, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

1. Get input Capacity and tasks in separate ArrayList s
2. Sort both ArrayList s in Desc order.
3. For the Highest task check the Highest available Server capacity.
3. If the task is bigger than any server capacity then there is no point in moving ahead.
4. If the same capacity as task is found then remove both task and capacity from respective ArrayList s.
5. If the Task is smalled than the Capacity then deduct from capacity
6. Reiterate till you find servers for all Tasks.

import java.io.Console;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
public class ServerCapacity {

    public static void main(String[] args) throws InterruptedException {
        Scanner c = new Scanner(System.in);

        System.out.println("Enter Servers capacity limits: ");
        String serCapLim = "8, 16, 8, 32"; //c.nextLine();
        serCapLim = "1,3";
        System.out.println("Enter Tasks capacity Need: ");
        String taskCapNeed = "18, 4, 8, 4, 6, 6, 8, 8"; //c.nextLine();
        taskCapNeed="4";

        String[] splits = serCapLim.split(",");
        ArrayList<Integer> serCaps = new ArrayList(splits.length);
        for (int i = 0; i < splits.length; i++) {
            serCaps.add(Integer.parseInt(splits[i].trim()));
        }

        splits = taskCapNeed.split(",");
        ArrayList<Integer> taskNeeds = new ArrayList(splits.length);
        for (int i = 0; i < splits.length; i++) {
            taskNeeds.add(Integer.parseInt(splits[i].trim()));
        }

        try {
            boolean flag = checkCapacity(serCaps, taskNeeds);
            System.out.println("flag:" + flag);
        } catch (Exception e) {
        }
    }

    public static boolean checkCapacity(ArrayList<Integer> serCaps, ArrayList<Integer> taskNeeds) throws Exception {
        //check if the capacity is in Limits
        if (serCaps.size() > 8 | taskNeeds.size() > 8) {
            throw new Exception("Either task or servers are not in limit");
        }

        //first sort those lists in desc order
        Collections.sort(taskNeeds, Collections.reverseOrder());
        
        //if the find returns true then 
        return findTaskAssignment(taskNeeds, serCaps);
    }
    
    /**
     * Finds the assignment of task on server and reiterates for remaining.
     * Find the assignment for the biggest Job first on the biggest capacity server.
     * @param taskNeeds
     * @param serCaps
     * @return 
     */
    private static boolean findTaskAssignment(ArrayList<Integer> taskNeeds, ArrayList<Integer> serCaps) {
        if(taskNeeds.size()==0)
            return true;        
        int task = taskNeeds.get(0);
        Collections.sort(serCaps, Collections.reverseOrder());
        System.out.println("task to be assigned:" + task);
        System.out.println("server Caps remaining:" + serCaps);
        
        boolean flag = false;
//        for(int i=0; i<serCaps.size(); i++){
            int i=0;
            int cap=serCaps.get(i);
            //if task is bigger than cap then there is no point
            if (task > cap) {
                return false;
            } //if task is same as cap then assign
            else if (task == cap) {
                serCaps.remove(Integer.valueOf(task));
//                return true;
                taskNeeds.remove(0);
            } //else if the same size is ther
            else if(serCaps.contains(task)){
                //if we just enter task then it considers as index so we have to cast to Integer object
                serCaps.remove(Integer.valueOf(task)); 
//                return true;
                taskNeeds.remove(0);
            }
            //else deduct that task from the cap
            else {
                serCaps.set(i, cap-task);                
//                return true;
                taskNeeds.remove(0);
            }
//        }
        System.out.println("Next iteration");
        return findTaskAssignment(taskNeeds, serCaps);
    }
}

- Satyen August 26, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

1. Get input Capacity and tasks in separate ArrayList s
2. Sort both ArrayList s in Desc order.
3. For the Highest task check the Highest available Server capacity.
3. If the task is bigger than any server capacity then there is no point in moving ahead.
4. If the same capacity as task is found then remove both task and capacity from respective ArrayList s.
5. If the Task is smalled than the Capacity then deduct from capacity
6. Reiterate till you find servers for all Tasks.

import java.io.Console;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
public class ServerCapacity {

    public static void main(String[] args) throws InterruptedException {
        Scanner c = new Scanner(System.in);

        System.out.println("Enter Servers capacity limits: ");
        String serCapLim = "8, 16, 8, 32"; //c.nextLine();
        serCapLim = "1,3";
        System.out.println("Enter Tasks capacity Need: ");
        String taskCapNeed = "18, 4, 8, 4, 6, 6, 8, 8"; //c.nextLine();
        taskCapNeed="4";

        String[] splits = serCapLim.split(",");
        ArrayList<Integer> serCaps = new ArrayList(splits.length);
        for (int i = 0; i < splits.length; i++) {
            serCaps.add(Integer.parseInt(splits[i].trim()));
        }

        splits = taskCapNeed.split(",");
        ArrayList<Integer> taskNeeds = new ArrayList(splits.length);
        for (int i = 0; i < splits.length; i++) {
            taskNeeds.add(Integer.parseInt(splits[i].trim()));
        }

        try {
            boolean flag = checkCapacity(serCaps, taskNeeds);
            System.out.println("flag:" + flag);
        } catch (Exception e) {
        }
    }

    public static boolean checkCapacity(ArrayList<Integer> serCaps, ArrayList<Integer> taskNeeds) throws Exception {
        //check if the capacity is in Limits
        if (serCaps.size() > 8 | taskNeeds.size() > 8) {
            throw new Exception("Either task or servers are not in limit");
        }

        //first sort those lists in desc order
        Collections.sort(taskNeeds, Collections.reverseOrder());
        
        //if the find returns true then 
        return findTaskAssignment(taskNeeds, serCaps);
    }
    
    /**
     * Finds the assignment of task on server and reiterates for remaining.
     * Find the assignment for the biggest Job first on the biggest capacity server.
     * @param taskNeeds
     * @param serCaps
     * @return 
     */
    private static boolean findTaskAssignment(ArrayList<Integer> taskNeeds, ArrayList<Integer> serCaps) {
        if(taskNeeds.size()==0)
            return true;        
        int task = taskNeeds.get(0);
        Collections.sort(serCaps, Collections.reverseOrder());
        System.out.println("task to be assigned:" + task);
        System.out.println("server Caps remaining:" + serCaps);
        
        boolean flag = false;
//        for(int i=0; i<serCaps.size(); i++){
            int i=0;
            int cap=serCaps.get(i);
            //if task is bigger than cap then there is no point
            if (task > cap) {
                return false;
            } //if task is same as cap then assign
            else if (task == cap) {
                serCaps.remove(Integer.valueOf(task));
//                return true;
                taskNeeds.remove(0);
            } //else if the same size is ther
            else if(serCaps.contains(task)){
                //if we just enter task then it considers as index so we have to cast to Integer object
                serCaps.remove(Integer.valueOf(task)); 
//                return true;
                taskNeeds.remove(0);
            }
            //else deduct that task from the cap
            else {
                serCaps.set(i, cap-task);                
//                return true;
                taskNeeds.remove(0);
            }
//        }
        System.out.println("Next iteration");
        return findTaskAssignment(taskNeeds, serCaps);
    }
}

- Satyen August 26, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

//n^2 greedy approach
#include    <iostream>
using namespace std;

int main()
{
    //int servercap[] = {8, 16, 8, 32};
    //int taskcap[] = {18, 4, 8, 4, 6, 6, 8, 8 };
    int servercap[] = {1,3,1,2,3,4};
    int taskcap[] = {4,3,1,2,3,1};
    int sizea = sizeof(servercap)/sizeof(servercap[0]);
    int sizeb = sizeof(taskcap)/sizeof(taskcap[0]);
    int i = 0;
    for(;i<sizeb;i++)
    {
        int minWasteIdx = -1;
        int wastage  = -1;
        int minwastage = 999;
        for(int j=0;j<sizea;j++)
        {
            if(taskcap[i] <= servercap[j])
            {
                wastage = servercap[j] - taskcap[i];
                if(wastage >= 0 && wastage < minwastage) {
                    minwastage = wastage;
                    minWasteIdx = j;
                }
            }
        }
        if(minWasteIdx == -1)
            break;
        servercap[minWasteIdx] -=taskcap[i];
    }
    if( i != sizeb)
        cout<<"No Sol Possible"<<endl;
    else {
        cout<<"Solution Possible"<<endl;
        for(int i=0;i<sizea;i++)
            cout<<servercap[i]<<"\t";
    }
    cout<<endl;
    return 0;
}

- amit August 30, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

public static boolean ReturnSeverCanDo(int task[],int capacity[])
		{
		Arrays.sort(task);
		Arrays.sort(capacity);
		String s=Arrays.toString(task);
		int sum_task=0;
		int sum_capacity=0;
		for(int i=0;i<task.length;i++)
		{
			sum_task+=task[i];
		}
		for(int i=0;i<capacity.length;i++)
		{
			sum_capacity+=capacity[i];
		}
	if((task[task.length-1]<capacity[capacity.length-1])&&(sum_task<=sum_capacity))
	{
		return true;
	}
	
	return false;
}

- deepjparekh September 03, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

public static boolean ReturnSeverCanDo(int task[],int capacity[])
		{
		Arrays.sort(task);
		Arrays.sort(capacity);
		String s=Arrays.toString(task);
		int sum_task=0;
		int sum_capacity=0;
		for(int i=0;i<task.length;i++)
		{
			sum_task+=task[i];
		}
		for(int i=0;i<capacity.length;i++)
		{
			sum_capacity+=capacity[i];
		}
	if((task[task.length-1]<capacity[capacity.length-1])&&(sum_task<=sum_capacity))
	{
		return true;
	}
	
	return false;
}

- deepjparekh September 03, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

#include<iostream>
#include<algorithm>
#define SIZE 10
#define TASKSIZE 3

using namespace std;

int main(){
    int server[SIZE] = {2,5,10,4,13,19,23,11,8,17};
    
    int task[TASKSIZE] = {30, 2, 1};
    sort(task, task+TASKSIZE);
    int *tempServer = new int[SIZE];
    
    sort(server,server + SIZE);
    sort(task, task+TASKSIZE);
    
    for(int i = 0; i<SIZE; i++)
        tempServer[i] = server[i];
    
    
    for(int i=TASKSIZE-1; i>=0; i--){
        for(int j=SIZE-1; j>=0;j--){
            if(task[i] < tempServer[j]){
                tempServer[j] = tempServer[j] - task[i];
                task[i] = 0;
                break;
            }
        }
    }
    
    int k=0;
    for(k=0; k<TASKSIZE; k++)
        if(task[k] != 0) break;
    if(k==TASKSIZE)
        cout<<"Request Served"<<endl;
    else
        cout<<"Request Cannot be Served"<<endl;
    
    
}

- Lalit September 28, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

#include<iostream>
#include<algorithm>
#define SIZE 10
#define TASKSIZE 3

using namespace std;

int main(){
    int server[SIZE] = {2,5,10,4,13,19,23,11,8,17};
    int task[TASKSIZE] = {30, 2, 1};
    int *tempServer = new int[SIZE];
    
    sort(server,server + SIZE);
    sort(task, task+TASKSIZE);
    
    for(int i = 0; i<SIZE; i++)
        tempServer[i] = server[i];
    
    
    for(int i=TASKSIZE-1; i>=0; i--){
        for(int j=SIZE-1; j>=0;j--){
            if(task[i] < tempServer[j]){
                tempServer[j] = tempServer[j] - task[i];
                task[i] = 0;
                break;
            }
        }
    }
    
    int k=0;
    for(k=0; k<TASKSIZE; k++)
        if(task[k] != 0) break;
    if(k==TASKSIZE)
        cout<<"Request Served"<<endl;
    else
        cout<<"Request Cannot be Served"<<endl;
    
    
}

- Lalit September 28, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

For each task, check if it can fit into any server.
DFS as long as tasks fit

public class ServerCapacity {

	// Server capacity
	public static boolean fits(int[] tasks, int[] servers, int n) {

		if (n == tasks.length)
			return true;

		for (int i = n; i < tasks.length; i++) {
			boolean serverFound = false;
			
			for (int j = 0; j < servers.length; j++) {
				if (servers[j] >= tasks[i]) {
					serverFound = true;
					servers[j] -= tasks[i];

					if (fits(tasks, servers, i + 1))
						return true;
					
					serverFound = false;
					servers[j] += tasks[i];
				}
			}
			
			// The task cannot fit into any servers
			if (!serverFound)
				return false;
		}

		return false;
	}

	public static void main(String[] args) {
		int[] servers = new int[] { 8, 16, 8, 30 };
		int[] tasks = new int[] {18, 4, 8, 4, 6, 6, 8, 8};

		System.out.println(fits(tasks, servers, 0));
	}
}

- frankierock October 12, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

bool SchedulingSolutionDP(std::vector<int>& serverCenter,
                           const std::vector<int>& tasks, const size_t taskIndex)
{
    if (tasks.empty()) {
        return true;
    }

    if (taskIndex >= (tasks.size() - 1)) {
        // the last corner case
        for (size_t index = 0; index < serverCenter.size(); ++index) {
            if (tasks[taskIndex] <= serverCenter[index]) {
                return true;
            }
        }
        return false;
    }

    for (size_t index = 0; index < serverCenter.size(); ++index) {
        if (tasks[taskIndex] <= serverCenter[index]) {
            // create sub-problem and call recursively
            serverCenter[index] -= tasks[taskIndex];
            if (SchedulingSolutionDP(serverCenter, tasks, taskIndex + 1)){
                // recover to the original problem
                serverCenter[index] += tasks[taskIndex];
                return true;
            }
            // recover to the original problem
            serverCenter[index] += tasks[taskIndex];
        }
    }

    return false;
}

Find more about the sub-problem description and test here: cpluspluslearning-petert.blogspot.co.uk/2014/11/dynamic-programming-task-schedulling.html

- Peter Tang November 02, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

What is the difference between using DFS recursion and the dynamic programming you mentioned? They are the same.

- allen.lipeng47 December 24, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 vote

This is a discrete bin packing problem - a variant of a classical bin packing ( en.wikipedia.org/wiki/Bin_packing_problem ), where bins are computers and items are tasks. Please note, that heuristic algorithms proposed in the discussion are incorrect solutions for this task (unless approximations are acceptable).
Generally, bin packing problem is NP-hard, however we can take advantage that weights and capacities are discrete (integers) and solve this with pseudo-polynomial dynamic programming algorithm with O(P) space and O(P) time where P is a product of capacities of all bins multiplied by a number of items. The storage is a multi-dimensional bit array which caches the partial solutions. dpCache[i][b0][b2]...[bk] is a bit which stores possibility of bin packing of first i items inside bins with capacity b0...bk.

Here's code:

class DiscreteBinPacking 
{
public:
	DiscreteBinPacking(const vector<int>& bins, const vector<int>& items)
		: bins(bins), remainingCapacity(bins), items(items)
	{
		// computing size of bit-vector to store multidimentional matrix
		// for caching partial solutions
		int size = items.size();
		for (int i = 0; i < bins.size(); i++) {
			size *= bins[i] + 1;
		}
		dpCache.resize(size);
		dpCacheMask.resize(size);
	}

	bool CanBePacked()
	{
		return CanBePacked(items.size());
	}

private:
	const vector<int> bins;
	const vector<int> items;

	vector<int> remainingCapacity;
	// two bit-vectors - they both represent multidimentional bit arrays to cache partial solutions
	vector<bool> dpCache;
	vector<bool> dpCacheMask;

	// returns true if bin packing is solvable for first i items
	bool CanBePacked(int i)
	{
		if (i == 0) return true;
		int cacheIndex = i - 1;
		for (int b = 0; b < bins.size(); b++) {
			cacheIndex *= bins[b] + 1;
			cacheIndex += remainingCapacity[b];
		}
		if (dpCacheMask[cacheIndex]) return dpCache[cacheIndex];

		bool result = false;
		int itemSize = items[i - 1];
		for (int b = 0; b < remainingCapacity.size() && !result; b++) {
			if (remainingCapacity[b] >= itemSize) {
				remainingCapacity[b] -= itemSize;
				result = CanBePacked(i - 1);
				remainingCapacity[b] += itemSize;
			}
		}
		dpCacheMask[cacheIndex] = true;
		dpCache[cacheIndex] = result;
		return result;
	}
};

- 0xF4 December 26, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

package com.company;

import java.util.Arrays;
import java.util.Collections;

public class Main {

public static void main(String[] args) {

int[] serverCapacity = {1, 3};
int[] taskCapacity = {4};
Arrays.sort(serverCapacity);
Arrays.sort(taskCapacity);
Data data = null;
for(int i = taskCapacity.length-1; i>-1; i--){
data = findCapacityInServer(serverCapacity, taskCapacity[i]);
serverCapacity = data.serverCapacity;
if(!data.foundCapacity){

System.out.println("Capacity Problem!");
break;
}
}
if(data.foundCapacity)
System.out.println("Looks Good!");

}

public static class Data{
public int serverCapacity[];
public boolean foundCapacity;
public Data(int servCapacity[], boolean foundCap){
serverCapacity = servCapacity;
foundCapacity = foundCap;
}
}

private static Data findCapacityInServer(int serverCapacity[], int taskCapacity){
for(int i = serverCapacity.length-1; i>-1; i--){
if(taskCapacity <= serverCapacity[i]){
serverCapacity[i] -= taskCapacity;
return new Data(serverCapacity, true);
}
}
return new Data(serverCapacity, false);
}
}

- GREED IS GOOD - DALJEET VIRDI January 31, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 vote

package com.company;

import java.util.Arrays;
import java.util.Collections;

public class Main {

    public static void main(String[] args) {

        int[] serverCapacity = {1, 3};
        int[] taskCapacity = {4};
        Arrays.sort(serverCapacity);
        Arrays.sort(taskCapacity);
        Data data = null;
        for(int i = taskCapacity.length-1; i>-1; i--){
            data = findCapacityInServer(serverCapacity, taskCapacity[i]);
            serverCapacity = data.serverCapacity;
            if(!data.foundCapacity){

                System.out.println("Capacity Problem!");
                break;
            }
        }
        if(data.foundCapacity)
            System.out.println("Looks Good!");

    }

    public static class Data{
        public int serverCapacity[];
        public boolean foundCapacity;
        public Data(int servCapacity[], boolean foundCap){
            serverCapacity = servCapacity;
            foundCapacity = foundCap;
        }
    }

    private static Data findCapacityInServer(int serverCapacity[], int taskCapacity){
        for(int i = serverCapacity.length-1; i>-1; i--){
            if(taskCapacity <= serverCapacity[i]){
                serverCapacity[i] -= taskCapacity;
                return new Data(serverCapacity, true);
            }
        }
        return new Data(serverCapacity, false);
    }
}

- GREED_IS_GOOD_DALJEET_VIRDI January 31, 2015 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 3 vote

I think its a best fit algorithm problem in which a number of processes are given and some memory blocks are given and we have to find the best fit memory block for a problem.

There might a more efficient way to slove this problem but i would like to solve this problem with the help of linked list and a array.

Lets suppose we have a linked list whose each node representing the memory space of each data center. Take your first example .
Servers capacity limits: 8, 16, 8, 32
Tasks capacity needs: 18, 4, 8, 4, 6, 6, 8, 8

Linked list : 32->16->8->8
array : 18,4,8,4,6,6,8,8
Now i will search best fit memory space (which is wasting minimum memory space after acqureing required space)of each process .

18 :
14->16->8->8
16->14->8->8

4:
16->14->4->8
16->14->8->4

8:
16->14->4

4:
16->14

6:
16->8

6:
16->2

8:
8->2

8:
2

- sdreamjain August 04, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

I thought the same way, but in each process we are re-sorting the linked list after the "best-fit" step. Is there a more optimized way to do this?

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

I think minor quicken the algo ?
1. We can use min heap for storing the server memory spaces. Search will be faster and insertion, deletion is easier to do.
2. You can sort task list as well in descending order and traverse through that order. This will help quicken the search process and you can remove the heap root, if it doesnt fit the task capacity.

- R August 04, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@R
so you are saying we should create min heap for each process ?

- sdreamjain August 05, 2014 | Flag
Comment hidden because of low score. Click to expand.
2
of 2 votes

Best fit will not work for following case
server capacity : 12 8
Task capacity need: 5 3 7 5

- jigs August 08, 2014 | Flag
Comment hidden because of low score. Click to expand.
-1
of 5 vote

I may be mistaken, but isn't this problem as simple as determining whether the highest server capacity is higher than the highest task capacity?

If so, all you have to do is make one pass through the server capacities, find the max. Make another pass through the task capacities, find the max. The comparison between the two determines if they can be scheduled.

- Jack August 04, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
2
of 2 votes

This is one of the case. Just comparing max capacities will not work. See below example:
Server: 4, 8
Tasks: 5, 7

- Mohit August 04, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

If your alogrithm is just to decrease the max job from the server with max capacity, it doesn't work for this

[8,6,2]
[5,4,3,2,1]

- Solomon Yang August 04, 2014 | Flag
Comment hidden because of low score. Click to expand.
1
of 1 vote

This is more closely related to the "Bin Filling" problem

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

@Solomon Yang, greedy algorithm still works here,
[8,6,2] , 5->8, 4->6, 3->3(8), 2->2(6), 1->2, right?

It will fail with following case,
[8,6,2]
[5,4,4,2,1]

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

Is there a hidden constraint in the problem that says we can't use sorting, because if we can use sorting then this problem can be solved easily, the following are the steps to do that -:

1) sort the servers by their capacity/memory limits, so for instance in the example shown above we will have our servers in the following order after sorting - 8,8,16,32

2) Perform the same step as above for the tasks that you want to allocate on these servers, so the sequence of jobs now becomes the following - 4,4,6,6,8,8,8,18

3) now for each job scan through the list of server's sorted by their memory limits and if a task can fit in the server decrease the capacity of the server by the size of the job in each step, so the final list becomes the following - 0,2,2,6 and hence you can return true when you have exhausted finding a best fit for all the jobs, else if you failed finding a best fit for a specific task you can return false immediately

- AnkitSablok19091989 August 04, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
1
of 1 vote

If your alogrithm is just to decrease the max job from the server with max capacity, it doesn't work for this

[8,6,2]
[5,4,3,2,1]

- Solomon Yang August 04, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

I understand what you are saying, got the problem working on it

- AnkitSablok19091989 August 04, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

[8,6,2]
[5,4,3,2,1]

the above algorithm still works for this test case as:
[8,6,2]
[5,4,3,2,1]


[3,2,2]
[3,2,1]

[0,0,1]

so it works

- anonymous August 12, 2014 | Flag
Comment hidden because of low score. Click to expand.
-1
of 1 vote

Sorry, my previous version has a bug. Here is working one.

class ServerCapacity:
    def __init__(self, list_capacity):
        self.list_capacity = sorted(list_capacity, reverse=True)
        self.answer = False

    def solution(self, list_job):
        self.list_job = sorted(list_job)
        self.recursive_walk(self.list_capacity, self.list_job)
        return self.answer

    def recursive_walk(self, list_capacity, list_job):
        # if job list is empty, done here
        if not len(list_job):
            self.answer = True
            return True

        # pop up the biggest job
        job = list_job.pop()

        # check if any server can take this job
        has_server = False
        for i, capacity in enumerate(list_capacity):
            if capacity >= job:
                list_capacity[i] -= job
                has_server = True

                #
                # if this assign doesn't work, return capacity, check
                # next server
                #
                if not self.recursive_walk(list_capacity, list_job):
                    list_capacity[i] += job
                    list_job.append(job)
                    has_server = False

        # if no server can handle this job, return False
        if not has_server:
            return False

if __name__ == "__main__":
    list_cap = [[1,3], [4,1], [8,16,8,32],       [8,6,2]]
    list_job = [[  4], [  4], [18,4,8,4,6,6,8,8],[5,4,3,3,1]]

    for cap, job in zip(list_cap, list_job):
        s = ServerCapacity(cap)
        print 'Solution :', s.solution(job)

- Solomon Yang August 04, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

could you please explain your algorithm than just writing lines of code.

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

Sames to be the same algorithm as mine.

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

Not sure we need dynamic programming for this,

if n servers are there and m number of tasks are there, first make max heap out of n servers, a second max heap of m taks,
pseudo code:
while(second max heap of m tasks is empty)
{
if(first server heap is empty)
return false;

mmax = get max task element out of second task heap
smax = get max server element of first server heap;

if(smax < mmax)
return false;

if(smax-mmax > 0)
insertintofirstserverheapandheapify(smax-mmax)
}

return true;

timecomplexity (mtaskitems log(servers) + mtaskitems log(mtaskitems ))

- notanexpert August 04, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
1
of 1 vote

Clearly, this is not a correct solution.
Let me take an example,
Server Limits: 8, 6
Task Limits: 6, 4, 4
The heap will be represented in similar order, since the nos. are sorted.
Your solution will map, Task 1 (6) to Server 1(8), with remainder 2. Task 2 will be mapped to Server 2(6). There will be no solution.

However, if we map Task 1(6) to Server 2(6) in the first case, then there is a solution possible as the other two tasks will be mapped to Server 1.

- Anon August 04, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

Try converting your max heap to a min heap for server capacity

- Ghost August 04, 2014 | Flag
Comment hidden because of low score. Click to expand.
0
of 0 votes

@anaon, yeah I was wrong thanks for the example, @ghost, may be I am wrong min heap solution will not work either
server: 12, 4 tasks, 2,4, 10
dynamic programming is the way to go, like an assembly line scheduler

- notanexpert August 04, 2014 | Flag
Comment hidden because of low score. Click to expand.
-1
of 1 vote

def canhandleload(sv, ld):
    sv = sorted(sv);
    ld = sorted(ld);    
    d = False;
    for x in reversed(ld) :
        d = False;
        for y in range(len(sv)):
            if(x <= sv[y]) :
                sv[y] =  sv[y]-x ;
                sv = sorted(sv);
                d  = True;
                break;
        if(d == False):
            return False;    
    return d;

s = [ 8, 16, 8, 32 ]
l = [18, 4, 8, 4, 6, 6, 8, 8 ]

print canhandleload(s,l);

- Nosh August 04, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

This works with all the examples I tried so far.

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

s = [12, 8]
l = [5, 3, 7, 5]

- maggot092 August 14, 2014 | Flag
Comment hidden because of low score. Click to expand.
-1
of 1 vote

Here's my 2 cents, correct me if I'm wrong.

1) Sort the server and task according to capacity/memory from large to small; return false if the some tasks are larger than the largest server;
2) Starting from large server, try to pack tasks in sequence into server, if some task can't fit in current server, go to smaller server and do the same thing;
3) Repeat until all task are filled. return false if there's left-over tasks

- Shiyu Luo August 05, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
0
of 0 votes

It doesn't work. Consider servers = (6, 5) and tasks = (5, 3, 3). A solution is 6 = 3 + 3 and 5 = 5. Your algorithm would send task 5 to server 6 and task 3 to server 5 and there would be no server for the other task 3.

- cassio.neri August 16, 2014 | Flag
Comment hidden because of low score. Click to expand.
-1
of 1 vote

What if you push back on a question like this since by the time any algorithm solves it, it would have been faster to just "randomly" assign the tasks to the servers and let them finish. There is no fast optimal solution to this. See "The Maximum Resource Bin Packing Problem", Boyar et al

I would just take the shortest job dump it on the server with the least capacity for which it fits and move forward. This greedy algorithm isn't optimal, but is a hell of a lot faster than getting the absolute correct answer and since the load balancer (ie your solution to this problem) is what is getting pounded the hardest in this system, it has to be fast to dish out the tasks. It's google, if they can't handle the load on their work servers perfectly, screw it, they'll buy another million machines ;-)

- Anonymous August 05, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 1 vote

Can we just simply get sums of two arrays? Then, sum of server capacity is greater than sum of tasks, it will be true. Am I missing anything?

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

Consider servers = (5, 5) and tasks = (6, 1). Although 5 + 5 = 10 > 7 = 6 + 1, so your algorithm returns true, no server can take the task 6. Notice that a task cannot be broken into smaller pieces.

- cassio.neri August 16, 2014 | Flag
Comment hidden because of low score. Click to expand.
-1
of 1 vote

Here is one more solution:

import std.stdio;
import std.algorithm;

void print(string name, const int[] array)
{
	write(name, ": [ ");
	foreach(int el; array) write(el, " ");
	writeln("]");
}

unittest
{
	int[] a = [2,5,1,2];
	sort!("a > b")(a);
	assert(a == [ 5, 2, 2, 1 ]);
	assert(isSorted!("a > b")(a));
}

bool TryToSchedulle(ref int[][] schedulled, int[]servers, int[]tasks)
{	
	if (tasks.length == 0) return true; // nothing process - success
	if (servers.length == 0) return false; // no servers left, but tasks exist - fail
	if (!isSorted!("a > b")(servers)) sort!("a > b")(servers); // if not reverse sorted - make reversed sort
	if (!isSorted!("a > b")(tasks)) sort!("a > b")(tasks);     // the same
	
	int[] skipped; // tasks
	int[] current; // list of tasks for the current server
	int capacity = servers[0]; // capacity of the current server
	foreach(task; tasks)
	{		
		if (capacity >= task)
		{						
			current ~= task; // run task in current server
			capacity -= task;	
		}
		else
		{
			skipped ~= task;
		}	
	}
	schedulled ~= current;	// add list of the task into solution
	return TryToSchedulle(schedulled, servers[1..$], skipped);	// make same with rest of the servers and skipped tasks
}

unittest
{
	{
		int[][] shedulled;
		assert(TryToSchedulle(shedulled, [],[]));
		assert(TryToSchedulle(shedulled, [1],[]));
		assert(TryToSchedulle(shedulled, [8, 16, 8, 32], [18, 4, 8, 4, 6, 6, 8, 8]));
		foreach(int[] tasks; shedulled) print (">", tasks);
	}

	{
		int[][] shedulled;
		assert(!TryToSchedulle(shedulled, [1,3], [4]));
	}

	{
		int[][] shedulled;
		assert(TryToSchedulle(shedulled, [8,6,2], [5,4,3,2,1]));
		foreach(int[] tasks; shedulled) print (">", tasks);
	}
}


int main(string[] argv)
{
    return 0;
}

Output:

>: [ 18 8 6 ]
>: [ 8 8 ]
>: [ 6 ]
>: [ 4 4 ]
>: [ 5 3 ]
>: [ 4 2 ]
>: [ 1 ]

- seb August 06, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 1 vote

class Program
{
static void Main(string[] args)
{
List<int> servers = new List<int>() { 8, 6, 2 };
List<int> tasks = new List<int>() { 6,5,3,2,1 };

bool result = BinFilling(servers, tasks);
}

//Servers: 8, 16, 8, 32
//Tasks: 18, 4, 8,4,6,6,8,8
//Servers: 8,6,2
//Tasks: 5,4,3,2,1

public static bool BinFilling(List<int> servers, List<int> tasks)
{
if (tasks.Count == 0)
return true;


for (int i = 0; i < servers.Count; i++)
{
for(int j=0; j< tasks.Count; j++)
{
if (tasks[j] != 0 && tasks[j] <= servers[i])
{
List<int> cloneServers = new List<int>(servers);
List<int> cloneTasks = new List<int>(tasks);
cloneServers[i] -= cloneTasks[j];
cloneTasks.RemoveAt(j);
if (BinFilling(cloneServers, cloneTasks))
{
return true;
}
}
}
}
return false;
}
}

- Joe August 07, 2014 | Flag Reply
Comment hidden because of low score. Click to expand.
-1
of 1 vote

What if sort the server and task first and assign the largest task to largest server, then add the smaller task to that server. The following code is the implementation of the algorithm above

public boolean arrange(int[] servers, int[] tasks){
    	Arrays.sort(servers);
    	Arrays.sort(tasks);
    	
    	for(int i = servers.length - 1; i >= 0; i--){
    		for(int j = tasks.length - 1; j >= 0; j--){
    			if(tasks[j] <= servers[i]){
    				servers[i] -= tasks[j];
    				tasks[j] = 0;
    			}
    		}
    	}
    	
    	for(int j = 0; j < tasks.length; j++){
    		if(tasks[j] > 0)
    			return false;
    	}
    	
    	return true;
    }

- xlshi August 11, 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