[Leetcode] 561. Array Partition I

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]范围内的整数)是有用的,否则空间复杂度会很高。
Happy coding!
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值