leetcode刷题记录之561

561、数组拆分 I

  给定长度为 2n 的数组, 你的任务是将这些数分成 n 对, 例如 (a1, b1), (a2, b2), …, (an, bn) ,使得从1 到 n 的 min(ai, bi) 总和最大。
示例 1:

输入: [1,4,3,2]
输出: 4
解释: n 等于 2, 最大总和为 4 = min(1, 2) + min(3, 4).

提示:

  • n 是正整数,范围在 [1, 10000].
  • 数组中的元素范围在 [-10000, 10000].

难度:简单  题目地址:https://leetcode-cn.com/problems/array-partition-i/

1、C语言代码:

int arrayPairSum(int* nums, int numsSize)
{
 	int n[20001] = { 0 }, i, j, sum;
 	for (i = 0; i < numsSize; i++)     //建立值、键哈希表,即基数排序
  		n[nums[i] + 10000]++;      //保证下标为正数
 	for (i = j = sum = 0; i < 20001; )    //将下标为 0、2、4 ... 的相加
  		if (n[i]){         //判断是否存在该数,若存在则判断是否偶数下标
   		if (j % 2 == 0) sum += i - 10000;  //偶数下标,累加
   			j++;         //计数
   		n[i]--;         //该值减 1
  	}	
  		else i++;        //不存在,跳过该值
 	return sum;
}

解释:

  • 排序,然后将下标为 0、2、4 … 个数相加即可。
  • 由于是纯数字,并且限定了数字范围,所以可使用基数排序达到 O(n) 复杂度。
  • 数字范围 [-10000, 10000],所以可创建 n[20001],对每个元素加 10000 使其变为正数。

知识点回顾: 本题若使用冒泡排序会超时,关于排序算法,将在数据结构篇中详细说明。

2、Java代码:

class Solution {
    public int arrayPairSum(int[] nums) {
        Arrays.sort(nums);
        int sum = 0;
        for (int i = 0; i < nums.length; i += 2) {
            sum += nums[i];
        }
        return sum;
    }
}

解释: 为了理解这种方法,让我们从不同的角度来看待问题。我们需要形成数组元​​素的配对,使得这种配对中最小的总和最大。因此,我们可以查看选择配对中最小值的操作,比如 (a,b)(a,b)(a,b) 可能会产生的最大损失 a−ba-ba−b (如果 a>ba > ba>b)。如果这类配对产生的总损失最小化,那么总金额现在将达到最大值。只有当为配对选择的数字比数组的其他元素更接近彼此时,才有可能将每个配对中的损失最小化。考虑到这一点,我们可以对给定数组的元素进行排序,并直接按排序顺序形成元素的配对。这将导致元素的配对,它们之间的差异最小,从而导致所需总和的最大化。

知识点回顾: 无。

3、Python代码:

class Solution:
    def arrayPairSum(self, nums: List[int]) -> int:
        return sum(sorted(nums)[::2])

解释: 排序 + 切片,再求和。

知识点回顾: 无。

4、JavaScript代码:

/**
 * @param {number[]} nums
 * @return {number}
 */
var arrayPairSum = function(nums) {
    //nums升序,取偶数位之和
    nums.sort((a,b)=>a-b);
    let res = 0;
    for(let i = 0;i < nums.length;i += 2){
        res += nums[i];
    }
    return res;
};

解释: 先进行排序,再对数组中下标为偶数的元素求和。

知识点回顾: 无。

你可能感兴趣的:(算法刷题)