I am trying to solve this problem:
A Professor of Physics gave projects to the students of his class. The students have to form a team of two for doing the project. The professor left the students to decide the teams. The number of students in a class will be even.
Each student has a knowledge level. It tells how much knowledge each student has. The knowledge level of a team is the sum of the knowledge levels of both the students.
The students decide to form groups such that the difference between the team with highest knowledge and the one with lowest knowledge is minimum.
Input
First line of the input will contain number of test cases t; In the next t lines the first number is n the number of students in the class followed by n integers denoting the knowledge levels of the n students
Output
Your output should be a single line containing the lowest possible difference between the team with highest knowledge and the one with lowest knowledge.
The solution boils down to calculate minimum difference between sum of two numbers in an unsorted array. So far I have tried:
- Sort the array.
- Add elements at positions i and n-i-1 and take its absolute difference with sum of elements at position i+1 and n-i.
- Store the differences in priority queue.
- Pop the top of priority queue to get the answer.
And, here is the code I have tried:
#include <bits/stdc++.h>
using namespace std;
int main()
{
ios_base::sync_with_stdio(false);
int T=0,num=0;
cin >> T;
while(T--){
cin >> num;
int *a = new int[num];
for(int i = 0; i < num; i++){
cin >> a[i];
}
sort(a,a+num);
priority_queue<int> pq;
for(int i = 0; i < num-2; i++){
int j = i+1;
pq.push(abs(a[i]+a[num-1-i]-a[j]-a[num-j-1]));
}
cout << pq.top()<< endl;
}
return 0;
}
This solution exceeds the time limit and my intuition is it may fail for some cases. The description and tags hint of a dynamic programming solution but somehow I am not able to deduce the optimal substructure. Can anyone help?
First of all, you are right that iteratively combining the best remaining student with the worst remaining student gives you the optimum result (see proof below).
However, you don't calculate the cost of that solution correctly. You have to run through all pairs of your combination in order to find the quality value of the best and the worst pair, and only after you found them both you can subtract their values. Btw. you don't need a priority queue to find the minimum (they are thought for more complex use cases where you insert and pop several times and even update the values in the queue), simple accumulator variables (
min
andmax
) will do. Assuming the arraya
is already sorted, the code could look like this:Now I want to proof why the pairing that you chose (iteratively pair the best remaining student with the worst remaining student) is optimal, which is essential here. If that doesn't hold, we need a whole other algorithm.
We prove it by showing that it's impossible to improve the solution given by that pairing.
If we wanted to improve it, we would have to reduce the difference between the best and the worst pair, which means either lower the best pair or raise the worst pair (or both).
Let's first show why lowering the best pair is impossible.
Let's give the pairs indices: The pair containing the highest number and the lowest number will be p_1 = (a_1, b_1), the pair with the next highest number and the next lowest number will be p_2 = (a_2, b_2) and so on, till p_n. For example:
Now one of those pairs, let's call it
p_m = (a_m, b_m)
(with 1 <= m <= n) will be the maximum pair. If we want to lower the maximum, we will have to break that pair up. But who can we paira_m
with, so the new pair has a lower sum? We need to find ab
, let's call itb_y
that is lower thanb_m
(otherwise this wouldn't be an improvement). We can only find a lowerb_y
by going upwards the list, i.e.y < m
. But the same goes for all pairs further up: If we have a pair further up (p_x
withx < m
) and try to find a new partnerb_y
for the olda_x
, we have to take into account thata_x >= a_m
, which makes certain choices ofy
impossible. If we choose ay>=m
, this implies thatb_y >= b_m
and thereforequality(a_x, b_y) = a_x + b_y >= a_m + b_y >= a_m + b_m = quality(p_m)
, which we wanted to avoid. Soy
has to be lower thanm
. If we take into account that restriction, them
possible values fora
({a_1,...,a_m}
) have onlym-1
possible partners{b_1,...b_(m-1)}
, so pairing is impossible. Therefore lowering the value of the best pair was impossible.In the above example: In order to reduce the maximum of 15, all pairs have to have values below 15. That implies that all the left-hand-side values of the pairs above or equal to the maximum pair (8, 8, 9, 10) would need partners that are below the maximum pair's right-hand-side partner (7), so only 1, 4, and 5 are possible.
The proof for showing that raising the worst pair is impossible works the same way with reversed comparison operators and switched
a
andb
(in that case we have too manyb
s for too fewa
s).