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:
n is a positive integer, which is in the range of [1, 10000].All the integers in the array will be in the range of [-10000, 10000].根据问题的描述可知,问题的解应该为把原始数组按照升序进行排序,再把奇数位置上的数组元素进行求和,即为所求。
算法证明如下(来源于参考链接):
假设对于每一对(ai,bi),都有bi >= ai。定义Sm = min(a1,b1)+ min(a2,b2)+ … + min(an,bn)。最大的Sm是这个问题的答案。由于bi >= ai,Sm = a1 + a2 + … + an。定义Sa = a1 + b1 + a2 + b2 + … + an + bn。对于给定的输入,Sa即为整个数组的和,是一个常数。定义di = | ai - bi |。由于bi >= ai,所以di = bi-ai, 即bi = ai+di。定义Sd = d1 + d2 + … + dn。所以Sa = a1 + (a1 + d1) + a2 + (a2 + d2) + … + an + (an + di) = 2Sm + Sd , 所以Sm =(Sa-Sd)/ 2。为得到最大Sm,给定Sa为常数,需要使Sd尽可能小。所以这个问题就是在数组中找到使di(ai和bi之间的距离)的和尽可能小的对。显然,相邻元素的这些距离之和是最小的。参考链接:
1) https://blog.csdn.net/whl_program/article/details/70667333 2) https://leetcode.com/problems/array-partition-i/discuss/102170/java-solution-sorting-and-rough-proof-of-algorithm
对原始输入数组进行排序,开始我采用的是冒泡排序,时间复杂度为O(n^2),严重超时,此处不赘述,也可以采用其他更快速的排序。
使用标准库函数sort()对数组排序, 然后对奇数位置上的数组元素求和。C++实现code如下:
class Solution { public: int arrayPairSum(vector<int>& nums) { sort(nums.begin(), nums.end()); int sum = 0; for(int i = 0; i<nums.size(); i+=2){ sum += nums[i]; } return sum; } };由于数组元素是整数,且已知元素的取值范围,所以可用基数排序来减少时间复杂度:
1) 首先创建20001个桶来分别存放数组元素取值个数。
2) 取值为[-10000, 10000]的数组元素的个数分别记在0号桶到20000号桶中,所以元素值nums[i]与桶的编号idx之间的关系为idx= nums[i] + 10000。
3) 由于需要对奇数位置数组求和,所以需要一个标志位flag来标记当前位置是否为奇数位置。
4)如果某个桶里具有多个相同取值的数组元素,那么标志位flag需要交替变换,且只有当当前桶为空时才能遍历下一号桶。
C++实现code如下:
class Solution { public: int arrayPairSum(vector<int>& nums) { vector<int> bucket(20001, 0); for (auto num : nums){ bucket[num + 10000] ++; } bool flag = true;// 控制是否为奇数位,因为所求是值等于升序排序后的数组的奇数位之和 int sum = 0; for (int i = 0; i<bucket.size();){ while (bucket[i]>0){ if (flag == true){ sum += i - 10000; bucket[i]--; flag = false; } else{ bucket[i]--; flag = true; } } i++; } return sum; } };