561. Array Partition I


Given an array of 2n integers, your task is to group these integers into n pairs of integer, say (a1, b1), (a2, b2), ..., (an, bn) which makes sum of min(ai, bi) for all i from 1 to n as large as possible.

Example 1:

Input: [1,4,3,2]

Output: 4
Explanation: n is 2, and the maximum sum of pairs is 4 = min(1, 2) + min(3, 4).

Note:

  1. n is a positive integer, which is in the range of [1, 10000].
  2. All the integers in the array will be in the range of [-10000, 10000].


Solution


Approach #1 Brute Force [Time Limit Exceeded]

Algorithm

The simplest solution is to consider every possible set of pairings possible by using the elements of the array. For generating all the possible pairings, we make use of a function permute(nums, current_index). This function creates all the possible permutations of the elements of the given array.

To do so, permute takes the index of the current element as one of the arguments. Then, it swaps the current element with every other element in the array, lying towards its right, so as to generate a new ordering of the array elements. After the swapping has been done, it makes another call to permute but this time with the index of the next element in the array. While returning back, we reverse the swapping done in the current function call.

Thus, when we reach the end of the array, a new ordering of the array's elements is generated. We consider the elements to be taken for the pairings such that the first element of every pair comes from the first half of the new array and the second element comes from the last half of the array. Thus, we sum up the minimum elements out of all these possible pairings and find out the maximum sum out of them.

The animation below depicts the ways the permutations are generated.

!?!../Documents/561_Array.json:1000,563!?!

Complexity Analysis

  • Time complexity : . A total of permutations are possible for elements in the array.
  • Space complexity : . Constant extra space is used.

Approach #2 Using Sorting [Accepted]

Algorithm

In order to understand this approach, let us look at the problem from a different perspective. We need to form the pairings of the array's elements such that the overall sum of the minimum out of such pairings is maximum. Thus, we can look at the operation of choosing the minimum out of the pairing, say as incurring a loss of (if ), in the maximum sum possible.

The total sum will now be maximum if the overall loss incurred from such pairings is minimized. This minimization of loss in every pairing is possible only if the numbers chosen for the pairings lie closer to each other than to the other elements of the array.

Taking this into consideration, we can sort the elements of the given array and form the pairings of the elements directly in the sorted order. This will lead to the pairings of elements with minimum difference between them leading to the maximization of the required sum.

Complexity Analysis

  • Time complexity : . Sorting takes time. We iterate over the array only once.

  • Space complexity : . Constant extra space is used.


Approach #3 Using Extra Array [Accepted]

Algorithm

This approach is somewhat related to the sorting approach. Since the range of elements in the given array is limited, we can make use of a hashmap , such that stores the frequency of occurence of element. This subtraction is done so as to be able to map the numbers in the range onto the hashmap.

Thus, now instead of sorting the array's elements, we can directly traverse the hashmap in an ascending order. But, any element could also occur multiple times in the given array. We need to take this factor into account.

For this, consider an example: nums: [a, b, a, b, b, a]. The sorted order of this array will be nums_sorted: [a, a, a, b, b, b]. (We aren't actually sorting the array in this approach, but the sorted array is taken just for demonstration). From the previous approach, we know that the required set of pairings is . Now, we can see that while choosing the minimum elements, will be chosen twice and will be chosen once only. This happens because the number of 's to be chosen has already been determined by the frequency of , leaving the rest of the places to be filled by . This is because, for the correct result we need to consider the elements in the ascending order. Thus, the lower number always gets priority to be added to the end result.

But, if the sorted elements take the form: nums_sorted: [a, a, b, b, b, b], the correct pairing will be . Again, in this case the number of 's chosen is already predetermined, but since the number of 's is odd, it doesn't impact the choice of in the final sum.

Thus, based on the above discussion, we traverse the hashmap . If the current element is occuring number of times, and one of the elements is left to be paired with other elements in the right region(considering a virtual sorted array), we consider the current element number of times and the next element occuring in the array number of times for the final sum. To propagate the impact of this left over chosen number, we make use of a flag . This flag is set to 1 if there is a leftover element from the current set which will be considered one more time. The same extra element already considered is taken into account while choosing an element from the next set.

While traversing the hashmap, we determine the correct number of times each element needs to be considered as discussed above. Note that the flag and the remains unchanged if the current element of the hashmap doesn't exist in the array.

Below code is inspired by @fallcreek

Complexity Analysis

  • Time complexity : . The whole hashmap of size is traversed only once.

  • Space complexity : . A hashmap of size is used.


Analysis written by: @vinod23