I have n tasks, each has a specific deadline and time it takes to complete. However, I cannot complete all tasks with in their deadlines. I need to arrange these tasks in such a way to minimize the task's deadline over shoot time. Consider this case(left values are dead lines and right side values are time the task takes):
2 2
1 1
4 3
These three tasks can be done optimally like this:
time 1 : task 2 - task1 complete; 0 overshoot for task2
time 2 : task 1
time 3 : task 1 - task2 complete; 1 overshoot for task1
time 4 : task 3
time 5 : task 3
time 6 : task 3 - task3 complete; 3 overshoot for task3
I need a faster algorithm for this; my goal is to find maximum overshoot of all overshoots(in above case its 3). Right now, i am sorting the tasks based on deadlines but its not fast, as when a new task is added, I should sort the whole list. Is there any other way?
After Lawrey's suggestion, I am using PriorityQueue but it is not giving me exact sorting.
This is my code:
class Compare2DArray implements Comparator<int[]> {
public int compare(int a[], int b[]) {
for (int i = 0; i < a.length && i < b.length; i++)
if (a[i] != b[i])
return a[i] - b[i];
return a.length - b.length;
}
}
public class MyClass{
public static void main(String args[]) {
Scanner scan = new Scanner(System.in);
int numberOfInputs= scan.nextInt();
PriorityQueue<int[]> inputsList = new PriorityQueue<int[]>(numberOfInputs,new Compare2DArray());
for (int i = 0; i < numberOfInputs; i++) {
int[] input = new int[2];
input[0] = scan.nextInt();
input[1] = scan.nextInt();
inputsList.add(input);
}
}
But this is sorting this queue of arrays
2 2
1 1
4 3
10 1
2 1
as
1 1
2 1
4 3
10 1
2 2
instead of
1 1
2 1
2 2
4 3
10 1
The same comparator works fine over List sorting. I am not getting whats wrong with PriorityQueue
Priority Queue is implemented using heaps. Hence, when you scan over the elements of priority queue it will not guarantee that it will give you all elements in sorted order. That is why you are not getting the desired sorted array.
I also faced the same problem for the question. I ended up using multimap in c++. But still the time complexity didn't improved much.
Unless you have a really long list of tasks, e.g. millions, it shouldn't be taking that long.
However, what you need is likely to be a PriorityQueue which has O(1) add and O(ln N) take
I was attempting the same question (Its from interviewstreet, I suppose). Did you get this order:
1 1, 2 1, 4 3, 10 1, 2 2
when you printed the heap? Did you try popping items off the heap one by one and check their order?
I am saying this since my implementation is in python and when I print the heap, I get the same order as you were saying. But that is not the point here, I think, since when I pop elements of the heap, one by one, I get a proper order that is:
1 1, 2 1, 2 2, 4 3, 10 1
Here is what my code in python looks like: (I am using the heapq library for implementing the priority queue)
To add elements to the heap:
[deadline, minutes] = map( int, raw_input().split() )
heapq.heappush( heap, ( deadline, minutes ) )
To remove them from the heap:
d, m = heapq.heappop( heap )
Here is the output I get when I print the heap, followed by popping elements from the heap step by step:
Heap: [(1, 1), (2, 1), (4, 3), (10, 1), (2, 2)]
Job taken: 1 1
Job taken: 2 1
Job taken: 2 2
Job taken: 4 3
Job taken: 10 1
Hope that helps!
Related
One of the professors of mine asked this question;
Imagine a thief entering a house. In the house, there are infinitely many items
that can have only one of three different weights: 1 kg, 3 kgs, and 5 kgs. All of the items are
discrete. The thief has a bag capacity of n kgs and strangely, he wants to steal the “smallest
number of items”.
He wants us to: Show that the greedy choice of taking the largest weight items into the bag first fails to lead to an optimal solution. But I claim that greedy is not failing. In any case taking as much as 5kg item is resulting in minimum number of items which is optimal. Is he wrong? I think greedy is optimal. Is there any case that greedy fails?
By the way, my solution:
public int stealRecursive(int bagCapacity) {
return stealRecursive(bagCapacity, 0);
}
private int stealRecursive(int bagCapacity, int numberOfItemsStolen) {
boolean canSteal5kg = bagCapacity - 5 >= 0;
boolean canSteal3kg = bagCapacity - 3 >= 0;
boolean canSteal1kg = bagCapacity - 1 >= 0;
if (canSteal5kg) {
return stealRecursive(bagCapacity - 5, numberOfItemsStolen + 1);
}
if (canSteal3kg) {
return stealRecursive(bagCapacity - 3, numberOfItemsStolen + 1);
}
if (canSteal1kg) {
return stealRecursive(bagCapacity - 1, numberOfItemsStolen + 1);
}
return numberOfItemsStolen;
}
Some of you stated that putting the code is not pointing anywhere, you are right I just put it to show both my effort and way of thinking. Because whenever I ask a problem without putting my code, I've been warned to show my effort first, due this is not a homework site. That's why I put my code. Sorry for confusing.
First, let's suppose that you have "taken" as many 5k items as possible, so you end up having
m = capacity mod 5
items to be stolen and you have already stolen 5n kilograms.
Cases
m == 0
5n
In this case you have n items and if you have stolen 1k or 3k items, then it would be worse (except for n = 0, in which case it does not make a difference whether you steal 0 items of 5 kilograms, 0 items of 3 kilograms or 0 items of 1 kilogram)
m == 1
5n + 1
In this case you have stolen n items of 5 kilograms and you steal an item of 1 kilogram additionally.
In the case of capacity = 6, you can steal 5 + 1 kilograms or 3 + 3 kilograms, leading to the same result, but the greater n is, the greater is the advantage of the greedy approach.
m == 2
We have 5n + 1 + 1
in the case of capacity = 7, we have 5 + 1 + 1 vs 3 + 3 + 1, but in general, greedy is better here as well.
m == 3
5n + 3
This is much better than 5n + 1 + 1 + 1
m == 4
5n + 3 + 1
In the case of 9, we have 5 + 3 + 1 vs 3 + 3 + 3, but in general, greedy is better
Conclusion
In general, greedy is better, but in some cases there is a tie. The reason is that there is an infinity of items that can be stolen. If there would be finite items of 5, 3, and 1 kilograms, respectively, then we can imagine scenarios like
5k items: 1
3k items: 3
1k items: 0
capacity: 9
Now, if you take the 5k item, then you will end up with a loot of 8, instead of a loot of 9. But we have infinite 5k, 3k and 1k items, so this is not a real scenario.
Consider an array of integers A having N elements in which each element has a one- to-one relation with another array element.
For each i, where 1≤i≤N there exists a 1−>1 relation between element i and element N−i+1
The Task is to perform following operations on this array which are as follows:
Given two integers (L,R) we have to swap each element in that range with its related element.(See Sample explanation below)
Sample Input
5
1 2 3 4 5
2
1 2
2 3
Sample Output
5 2 3 4 1
Explanation
For first query,we will swap 1 with 5 and 2 with 4.
Now the array becomes- 5 4 3 2 1
Similarly now ,for the second query we will swap 4 with 2 and 3 with itself.
So the final array will be 5 2 3 4 1
My Program goes like this:
import java.util.Scanner;
public class ProfessorAndOps {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner in=new Scanner(System.in);
int n=in.nextInt();//length of array
int a[]=new int[n];//array declaration
for(int i=0;i<n;i++){
//inputting array elements
a[i]=in.nextInt();
}
int q=in.nextInt();//number of queries
for(int i=0;i<q;i++){
int l=in.nextInt();//left limit
int r=in.nextInt();//right limit
//swapping while iterating over the given range of array elements:
for(int j=l-1;j<=r-1;j++){
int temp=a[j];
a[j]=a[n-j-1];
a[n-j-1]=temp;
}
}
//Printing the output array:
for(int i=0;i<n;i++){
if(i!=n-1){
System.out.print(a[i]+" ");
}
else{
System.out.println(a[i]);
}
}
}
}
I could only come up with BruteForce solution. I'm pretty sure there will be some pre-processing step or some optimisation technique with l and r variables, whatever I could think of, giving me wrong answer. Please help me optimise this code. To be specific, I would need my code's time complexity to be reduced from O(N+ Q*(R-L)) to something like O(Q+N)
Here's an O(Q + N) time, O(N) space algorithm. Imagine a list of the corresponding swap counts only for L and R over the elements (we'll use a negative number for the R counts). What if we maintained a virtual stack while traversing it? (By "virtual," I mean it's not a real stack, just an integer that bears some theoretical similarity.)
For example:
1 2 3 4 5 6 7 8 9 10
O(Q) processing:
q [1,3]
1 9 8 7 5 ... <- what would happen to the array
0 1 0 -1 0 <- counts (what we actually store)
q [2,4]
1 9 3 4 6 ... <- what would happen to the array
0 1 1 -1 -1 <- counts (what we actually store)
O(N) traversal:
index 0 didn't move, no change, stack: 0
index 1 moved once, odd count, changed, stack: 1
index 2 moved 2 (stack + 1), even count, no change, stack: 2
index 3 moved 2 (stack), even count, no change, stack: 2 - 1
index 4 moved 1 (stack), odd count, changed, stack: 1 - 1
I have this simple code sample that I don't understand.
// Compute integer powers of 2.
class Power {
public static void main (String args[]) {
int e, result;
for (int i = 0; i < 10; i++) {
result = 1;
e = i;
while (e > 0) {
result *= 2;
e--;
}
System.out.println("2 to the " + i + " power is " + result);
}
}
}
Producing this output.
2 to the 0 power is 1
2 to the 1 power is 2
2 to the 2 power is 4
2 to the 3 power is 8
2 to the 4 power is 16
2 to the 5 power is 32
2 to the 6 power is 64
2 to the 7 power is 128
2 to the 8 power is 256
2 to the 9 power is 512
Questions:
How come result is not always 2, since it's being re-initialized every time the for loop is entered?
The e-- decrement doesn't do a thing either, does it? Since, again, e is being set equal to i afresh on every iteration.
Thanks.
How come result is not always 2, since it's being re-initialized every
time the for loop is entered?
Yes, it is being re-initialized but only in the first loop. Your inner loop is looping while(e > 0) and double result at each iteration. Then once you are done looping, you pring the result and restart. The value of result will depend on e which define the number of times result is doubled.
The e-- decrement doesn't do a thing either, does it? Since, again, e
is being set equal to i afresh on every iteration.
Again, yes it is being set back to i at each iteration but that doesn't mean it is useless. At each iteration, e is set back to the new value of i, and then you use it to create an inner loop while e > 0 where at each iteration you decrement e of 1 and double the result.
The two questions kind of go together.
You see, e is set to i which is actually INCREASED each iteration.
And the higher e is, the more often the inner while will be worked through.
So for example in your 3rd for iteration
i = 2
e = 2
result = 1
So first while:
result = result*2 = 1*2 = 2
e = 1
e is still > 0 so after the second while:
result = result*2 = 2*2 = 4
e = 0
And there we go.
e-- did something twice and result is NOT 2.
result and e are re-initialized at the top of the for loop, but are modified within the while loop before result is displayed at the bottom of the for loop.
I have to do a little assignment at my university:
I have a server that runs 'n' independent services. All these services started at the same time in the past. And every service 'i' writes 'b[i]' lines to a log file on the server after a certain period of time 's[i]' in seconds. The input consist of 'l' the number of lines of the log file and 'n' the number of services. Then we have in the next 'n' lines for every service i: 's[i]' the period as mentioned and 'b[i]' the number of lines the services writes to the log file.
I have to compute from the number of lines in the log file, how long ago, in seconds, the programs all started running. Example:
input:
19 3
7 1
8 1
10 2
Output:
42
I have to use divide and conquer, but I can't even figure out how to split this in subproblems. Also I have to use this function, where ss is the array of the periods of the services and bs the number of lines which each services writes to the log file:
long linesAt(int t, int[] ss, int[] bs) {
long out = 0;
for (int i = 0; i < ss.length; i++) {
// floor operation
out += bs[i] * (long)(t/ss[i]);
}
return out;
ss and bs are basically arrays of the input, if we take the example they will look like this, where the row above is the index of the array:
ss:
0 1 2
7 8 10
bs:
0 1 2
1 1 2
It is easily seen that 42 should be the output
linesAt(42) = floor(42/7)*1+floor(42/8)*1+floor(42/10)*2 = 19
Now I have to write a function
int solve(long l, int[] ss, int[] bs)
I already wrote some pseudocode in brute force, but I can't figure out how to solve this with the divide and conquer paradigm, my pseudocode looks like this:
Solve(l, ss, bs)
out = 0
t = 0
while (out != l)
out = linesAt(t, ss, bs)
t++
end while
return t
I think I have to split l in some way, so to calculate the time for smaller lengths. But I don't really see how, because when you look at this it doesn't seem to be possible:
t out
0..6 0
7 1
8 2
9 2
10 4
11..13 4
14 5
15 5
16 6
17..19 6
20 8
...
40 18
42 19
Chantal.
Sounds like a classic binary search would fit the bill, with a prior step to obtain a suitable maximum. You start with some estimate of time 't' (say 100) and call linesAt to obtain the lines for that t. If the value returned is too small (i.e. smaller than l), you double 't' and try again, until the number of lines is too large.
At this point, your maximum is t and your minimum is t/2. You then repeatedly:
pick t as the point halfway between maximum and minimum
call linesAt(t,...) to obtain the number of lines
if you've found the target, stop.
if you have too many lines, adjust the maximum: maximum = t
if you have too few lines adjust the minimum: minimum = t
The above algorithm is a binary search - it splits the search space in half each iteration. Thus, it is an example of divide-and-conquer.
You are trying to solve an integer equation:
floor(n/7)*1+floor(n/8)*1+floor(n/10)*2 = 19
You can remove the floor function and solve for n and get a lower bound and upper bound, then search between these two bounds.
Solving the following equation:
(n/7)*1+(n/8)*1+(n/10)*2 = 19
n=19/(1/7+1/8+2/10)
Having found n, which range of value m0 will be such that floor (m0 / 7) = floor (n/7)?
floor (n/7) * 7 <= m0 <= (ceiling (n/7) * 7) - 1
In the same manner, calculate m1 and m2.
Take max (mi) as upperbound and min(mi) as lowerbound for i between 1 and 3 .
A binary search at this point will probably be an overkill.
After a tennis tournament each player was asked how many matches he had.
An athlete can't play more than one match with another athlete.
As an input the only thing you have is the number of athletes and the matches each athlete had. As an output you will have 1 if the tournament was possible to be done according to the athletes answers or 0 if not. For example:
Input: 4 3 3 3 3 Output: 1
Input: 6 2 4 5 5 2 1 Output: 0
Input: 2 1 1 Output: 1
Input: 1 0 Output: 0
Input: 3 1 1 1 Output: 0
Input: 3 2 2 0 Output: 0
Input: 3 4 3 2 Output: 0
the first number of the input is not part of the athletes answer it's the number of athletes that took part in the tournament for example in 6 2 4 5 5 2 1 we have 6 athletes that took part and their answers were 2 4 5 5 2 1.
So far this is what we wrote but didn't work that great:
import java.util.Scanner;
import java.util.Arrays;
public class Tennis {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
String N;
int count;
int sum = 0;
int max;
int activeAthletes;
int flag;
System.out.printf("Give: ");
N = input.nextLine();
String[] arr = N.split(" ");
int[] array = new int[arr.length];
for (count = 0; count < arr.length; count++) {
array[count] = Integer.parseInt(arr[count]);
//System.out.print(arr[count] + " ");
}
for (count = 1; count < arr.length; count++) {
sum += array[count];
}
//System.out.println("\n" + sum);
activeAthletes = array[0];
for (count = 1; count < array.length; count++) {
if (array[count] == 0) {
activeAthletes--;
}
}
max = array[1];
for (count = 2; count < array.length; count++) {
if (array[count] > max) {
max = array[count];
}
}
// System.out.println(max);
if ((sum % 2 == 0) && (max < activeAthletes)) {
flag = 1;
} else{
flag = 0;
}
System.out.println(flag);
}
}
I do not want a straight solution just maybe some tips and hints because we really have no idea what else to do and I repeat even though I'll tag it as a homework (because I feel the moderators will close it again) it is not, it's just something my brother found and we are trying to solve.
Well many of you have answered and I'm really grateful but as I have work tomorrow I need to go to sleep, so I'll probably read the rest of the answers tomorrow and see what works
Not sure if it works 100%, i would go like:
Sort input
for each element going from right to left in array (bigger to smaller)
based on value n of element at index i decrease n left elements by 1
return fail if cant decrease because you reached end of list or value 0
return success.
This logic (if correct) can lead whit some modifications to O(N*log(N)) solution, but I currently think that that would be just too much for novice programmer.
EDIT:
This does not work correct on input
2 2 1 1
All steps are then (whitout sorting):
while any element in list L not 0:
find largest element N in list L
decrease N other values in list L by 1 if value >= 1 (do not decrease this largest element)
return fail if failure at this step
set this element N on 0
return OK
Here's a hint. Answer these questions
Given N athletes, what is the maximum number of matches?
Given athlete X, what is the maximum number of matches he could do?
Is this sufficient to check just these? If you're not sure, try writing a program to generate every possible matching of players and check if at least one satisfies the input. This will only work for small #s of atheletes, but it's a good exercise. Or just do it by hand
Another way of asking this question, can we create a symmetric matrix of 1s and 0s whose rows are equal the values. This would be the table of 'who played who'. Think of this like an N by N grid where grid[i][j] = grid[j][i] (if you play someone they play you) and grid[i][i] = 0 (no one plays themselves)
For example
Input: 4 3 3 3 3 Output: 1
Looks like
0 1 1 1
1 0 1 1
1 1 0 1
1 1 1 0
We can't do this with this one, though:
Input: 3 2 2 0 Output: 0
EDIT
This is equivalent to this (from Degree (graph theory))
Hakimi (1962) proved that (d1, d2, ..., dn) is a degree sequence of a
simple graph if and only if (d2 − 1, d3 − 1, ..., dd1+1 − 1, dd1+2,
dd1+3, ..., dn) is. This fact leads to a simple algorithm for finding
a simple graph that has a given realizable degree sequence:
Begin with a graph with no edges.
Maintain a list of vertices whose degree requirement has not yet been met in non-increasing order of residual degree requirement.
Connect the first vertex to the next d1 vertices in this list, and then remove it from the list. Re-sort the list and repeat until all
degree requirements are met.
The problem of finding or estimating the number of graphs with a given
degree sequence is a problem from the field of graph enumeration.
Maybe you can take the array of athletes' match qties, and determine the largest number in there.
Then see if you can split that number into 1's and subtract those 1's from a few other members of the array.
Zero out that largest number array member, and remove it from the array, and update the other members with reduced values.
Now, repeat the process - determine the new largest number, and subtract it from other members of the array.
If at any point there are not enough array members to subtract the 1's from, then have the app return 0. otherwise continue doing it until there are no more members in the array, at which point you can have the app return 1.
Also, remember to remove array members that were reduced down to zero.
Your examples can all trivially be solved by counting the matches and looking whether they divide by 2.
A problem not covered by your examples would be a player, who has more games than the sum of the other players:
Input: 4 5 1 1 1 Output: 0
This can be complicated if we add more players:
Input: 6 5 5 5 1 1 1 Output: 0
How to solve this question? Well, remove one game pairwise from the maximum and the minimum player, and see what happens:
Input: 6 5 5 5 1 1 1
Input: 5 5 5 4 1 1 -
Input: 4 5 4 4 1 - -
Input: 3 4 4 4 - - -
It violates the rule:
An athlete can't play more than one match with another athlete.
If 3 players are left, they can't have had more than 2 games each.
Edit: Below solution passes some invalid inputs as valid. It's a fast way to check for definite negatives, but it allows false positives.
Here's what a mathematician would suggest:
The sum of the number of matches must be even. 3 3 4 2 1 sums to 13, which would imply someone played a match against themselves.
For n players, if every match eliminates one player at least n-1 distinct matches must be played. (A knockout tournament.) To see this, draw a tree of matches for 2, 4, 8, 16, 32... players, requiring 1, 3, 7, 31... matches to decide a winner.
For n players, the maximum number of matches if everyone plays everyone once, assuming no repeat matches, is n choose 2, or (n!)/(2!)(n-2)! (Round robin tournament). n! is the factorial function, n! = n * n-1 * n-2 * ... * 3 * 2 * 1..
So the criteria are:
Sum of the number of matches must be even.
Sum of the number of matches must be at least 2n-2. (Note the multiplication by 2 - each match results in both players increasing their count by one.)
Sum of the number of matches must be at most 2 * n choose 2.
[Edit] Each player must participate in at least one match.
If your tournament is a cross between a knockout tournament and a round robin tournament, you could have somewhere between n-1 and n choose 2 matches.
Edit:
If any player plays more than n-1 matches, they played someone at least twice.
If your tournament is a knockout tournament ordered so that each player participates in as few matches as possible, then each player can participate in at most log_2(n) matches or so (Take log base 2 and round up.) In a tournament with 16 players, at most 4 matches. In a tournament of 1024 players, at most 10 matches.