题目: 
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. 
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].

思路: 
就是给2n个数分组,两两一组,使得每一组中最小的那个数的和最大。这个问题其实很有趣,最终我们要做的事情就是选出来的的数字是两个数中最小的,但却要尽可能的大,这样才能使得n个数字求和之后得到的结果最大。不妨这样想,先把这些数字数字排序,得到由小到大的有序数组,从最大的数字挑起,最大的数字显然最后不会参与求和,那它该挑谁走才能为最后的加和贡献一个大的数字呢?显然是第二大的数;由此类推,第三大应该和第四大数字配对,也就是说对有序数组两两分组即可。问题的关键变为选择高效的排序算法
关于为何要这么选数字,严格证明如下:

  • 假设对于每一对i,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之间的距离)的和尽可能小的对。显然,相邻元素的这些距离之和是最小的

排序问题是个老生常谈的问题,我最开始用的冒泡排序,但是最后的4组测试数据没有通过,报错超时,因为O(n^2)的复杂度处理较长序列时是很费时间的,但是冒泡排序作经典的排序算法,应当掌握,代码如下:

 1 class Solution {
 2 public:
 3     int arrayPairSum(vector<int>& nums) {
 4         int temp;
 5         for(int i=1;i<nums.size();i++)
 6         {
 7           for(int j=0;j<nums.size()-i;j++)
 8           {
 9               if(nums[j]>nums[j+1])
10               {
11                   temp = nums[j];
12                   nums[j]=nums[j+1];
13                   nums[j+1]=temp;
14               }
15           }
16         }
17         int sum=0;
18         for(int i=0;i<nums.size();i=i+2)
19            sum+=nums[i];
20        return sum;
21     }
22 };
View Code

相关文章: