数组拆分Ⅰ
1.题目描述
给定长度为 2n 的整数数组 nums ,你的任务是将这些数分成 n 对, 例如 (a1, b1), (a2, b2), ..., (an, bn) ,使得从 1 到 n 的 min(ai,bi)min(ai, bi)min(ai,bi) 总和最大。
返回该 最大总和 。
2.示例
示例 1:
输入:nums = [1,4,3,2]
输出:4
解释:所有可能的分法(忽略元素顺序)为:
1. (1, 4), (2, 3) -> min(1, 4) + min(2, 3) = 1 + 2 = 3
2. (1, 3), (2, 4) -> min(1, 3) + min(2, 4) = 1 + 2 = 3
3. (1, 2), (3, 4) -> min(1, 2) + min(3, 4) = 1 + 3 = 4
所以最大总和为 4
示例 2:
输入:nums = [6,2,6,5,1,2]
输出:9
解释:最优的分法为 (2, 1), (2, 5), (6, 6). min(2, 1) + min(2, 5) + min(6, 6) = 1 + 2 + 6 = 9
3.读题
今天这道题还是挺有意思的。首先,我们要把长度为2n的数组划分为n组,每一组有两个数字。然后,在划分后每一组两个数之间就会有一个较小值,我们将这n组的n个较小值求和。而我们的目的就是,找出一种划分的方法,使得划分后的这个求和的值,在所有划分方法中是最大的。
4.思路
其实一看到这个题目,第一感觉就是先排序,然后取奇数位置的值相加,就是答案。结果真的是这么做的。后来想了一下,这个是很容易证明的。证明如下:
假设2n个数字排序后为(c1,c2,c3,⋯ ,cn,cn+1,⋯ ,c2n−1,c2n)(c_1,c_2,c_3,\cdots,c_n,c_{n+1},\cdots,c_{2n-1},c_{2n})(c1,c2,c3,⋯,cn,cn+1,⋯,c2n−1,c2n),我们将其划分成n组如下:(a1,b1),(a2,b2),⋯ ,(an−1,bn−1),(an,bn)(a_1,b_1),(a_2,b_2),\cdots,(a_{n-1},b_{n-1}),(a_n,b_n)(a1,b1),(a2,b2),⋯,(an−1,bn−1),(an,bn),且对于每一组都有,ai<bi,ai<ai+1a_i<b_i,a_i<a_{i+1}ai<bi,ai<ai+1。那么,取其中任意一组(aj,bj)(a_j,b_j)(aj,bj),则有以下结论:
- 1:由于aj<aj+1a_j<a_{j+1}aj<aj+1,而一共有n个a,也就是说aj<aj+1<aj+2<⋯<ana_j<a_{j+1}<a{j+2}<\cdots<a_naj<aj+1<aj+2<⋯<an。因此cic_ici中大于aja_jaj的至少有n−jn-jn−j个
- 2:由于aj<aj+1<aj+2<⋯<ana_j<a_{j+1}<a_{j+2}<\cdots<a{n}aj<aj+1<aj+2<⋯<an,且对于每一组(ai,bi)(a_i,b_i)(ai,bi)都有ai<bia_i<b_iai<bi,因此至少有aj<bj,aj<bj+1,⋯ ,aj<bna_j<b_j ,a_j<b_{j+1},\cdots ,a_j<b_naj<bj,aj<bj+1,⋯,aj<bn,因此cic_ici中大于aja_jaj的至少还有n−j+1n-j+1n−j+1个
由以上两点可以得出,cic_ici中大于aja_jaj的至少有2(n−j)+12(n-j)+12(n−j)+1个,由于cjc_jcj已经排序,所以显然有aj≤c2n−(2(n−j)+1)a_j\le c_{2n-(2(n-j)+1)} aj≤c2n−(2(n−j)+1)即aj≤c2j−1a_j\le c_{2j-1}aj≤c2j−1
所以,所有aia_iai的和满足:
∑i=1nan≤∑i=1nc2j−1 \sum_{i=1}^na_n \le \sum_{i=1}^nc_{2j-1} i=1∑nan≤i=1∑nc2j−1
但是只要我们分组取(ai,bi)=(c2i−1,c2i)(a_i,b_i)=(c_{2i-1},c_{2i})(ai,bi)=(c2i−1,c2i),那么就有∑i=1nan=∑i=1nc2j−1 \sum_{i=1}^na_n = \sum_{i=1}^nc_{2j-1} i=1∑nan=i=1∑nc2j−1
所以,关于aia_iai的和的不等式可以取到最大值,此时该最大值即为∑i=1nc2j−1\sum_{i=1}^nc_{2j-1}∑i=1nc2j−1,取法为将该数组排序后,从小到大开始每两个相邻的元素为一组。此时该和即为数组奇数下标位置的数字的和(由于java中数组下标从0开始,在程序中就变成了求偶数位置上的数字的和)。
5.代码
分析很多,但是结论简单,所以代码也很少:
class Solution {
public int arrayPairSum(int[] nums) {
Arrays.sort(nums);
int ans = 0;
for(int i=0;i<nums.length;i+=2){
ans+=nums[i];
}
return ans;
}
}
该博客介绍了LeetCode的第561题——数组拆分I,目标是将一个长度为2n的数组拆分成n对,使1到n的min(ai, bi)之和最大化。博主通过分析证明了最佳策略是将排序后的数组中奇数位置的元素组合,即求偶数位置元素的和,得到了最大总和。"
115611184,904426,Java语法:标识符、关键字与命名规范解析,"['Java语法', '编程规范', '基础概念']

519

被折叠的 条评论
为什么被折叠?



