Description:
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:
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].
目标:让这n对整数中的最小值之和达最大。
解法一:(Accepted: beat 63%)
思路:
排序,从0开始,每隔一个数相加。
使n对整数最小值之和达最大即在有序状态下将偶数下标值相加。
(如果是求最小值之和达最小即前n个数相加)
class Solution {
public:
int arrayPairSum(vector<int>& nums) {
sort(nums.begin(),nums.end());//vector使用sort函数排序
int l = nums.size();
total=0;
for(int i = 0; i <= l-2 ; i=i+2)
{
total+=nums[i];
}
return total;
}
};
- 利用sort函数排序,sort函数本质是快速排序
- 实践证明for循环比while循环要快很多
解法二:哈希表(用空间换时间)
O(n)
O
(
n
)
(Accepted: beat 90%)
思路:
#####The key of this solution is to use the element itself as the index.
为了便于理解,假设所有整数范围都在[0,10000]而非[-10000,10000]。创造一个叫hash的数组(vector),它的大小为10000-0+1=10001,这个数组是用于记录nums数组中每个元素的出现次数。
这个方法的关键在于:把nums数组元素本身作为hash数组的下标。
例如,我们遍历nums数组,遇到2的时候,执行hash[2]++;
;遇到7的时候,执行hash[7]++;
,等等。这也是第一个循环的作用。
对于第二个循环,我们遍历哈希表hash。如果hash[0]==2
,说明在nums数组中0有2个,也就是排序之后的nums从两个0开始,如果hash[1]=3
,说明这两个0之后有3个1。
flag
在这里的作用是记录当前数是否是nums排序后的偶数下标的数。因为前面解法一提到,使n对整数最小值之和达最大即在有序状态下将下标为偶数的值相加。而total
是用来计算求和,最后返回的。
需要注意的是,当处理完哈希表某一位置时仍不为0时,如hash[3]=2
变成了hash[3]=1
,此时还应该继续处理这个位置,因此第二个循环中i不会加一。只有当hash[3]=0
时,i才加一,处理下一个位置,也就是else i++;
的时候。
而这个problem里,整数范围是[-10000,10000],因此hash的capacity应为10000-(-10000)+1=20001。为了避免下标为负数,在第一个循环中使用hash[nums[i]+10000]++;
,而在第二个循环中,要把这加上的10000减回来,故有result+=i-10000;
class Solution {
public:
int arrayPairSum(vector<int>& nums) {
vector<int> hash(20001,0);
for(int i=0; i<nums.size();i++)
{
hash[nums[i]+10000]++;
}
int result=0, flag=0;
for(int i = 0;i<20001;)
{
if((hash[i]>0)&&(flag==0))
{
result+=i-10000;
hash[i]--;
flag = 1;
}
else if((hash[i]>0)&&(flag==1))
{
hash[i]--;
flag = 0;
}
else
i++;
}
return result;
}
};
- 这个方法在已知原数组nums元素的范围以及这个范围不是很大的情况下(如nums数组的元素都是[INT_MIN,INT_MAX]范围内的整数)是有用的,否则空间复杂度会很高。