Swift - LeetCode - 数组拆分

147 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第32天,点击查看活动详情

题目

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

返回该 最大总和

示例 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

方法一:排序

思路及解法

不失一般性,我们令每一组 (ai,bi)(a_i, b_i) 满足 aibia_i \leq b_i(若不满足,交换二者即可),这样我们需要求得的总和

i=1nmin(ai,bi)\sum_{i=1}^n \min(a_i, b_i)

就等于所有 aia_i 的和

(1)(1): i=1nai\sum_{i=1}^n a_i

接下来,我们将所有的 (ai,bi)(a_i, b_i) 按照升序排序,使得 a1a2ana_1 \leq a_2 \leq \cdots \leq a_n。这样一来,对于任意的 aja_j

  • 它不大于 aj+1,aj+2,,ana_{j+1}, a_{j+2}, \cdots, a_n
  • 它不大于 bjb_j
  • 由于 aibia_i \leq b_i 对于任意的 ii 恒成立,因此它不大于 bj+1,bj+2,,bnb_{j+1}, b_{j+2}, \cdots, b_n

由于 aja_j 不大于 {a}\{a\} 中的 njn-j 个元素,也不大于 {b}\{b\} 中的 nj+1n-j+1 个元素,而这些元素都是从 nums\textit{nums} 中而来的,因此 aja_j 在数组 nums\textit{nums} 中「从大到小」至少排在第 (nj)+(nj+1)+1=2(nj+1)(n-j) + (n-j+1) + 1 = 2(n-j+1) 个位置,也就是「从小到大」至多排在第 2n2(nj+1)+1=2(j1)+12n - 2(n-j+1) + 1 = 2(j-1) + 1 个位置,这里位置的编号从 11 开始,即

ajc2(j1)+1a_j \leq c_{2(j-1)+1}

其中数组 cc 是将数组 nums\textit{nums} 升序排序得到的结果,代入 (1)(1) 式即可得到

(2)(2): i=1naii=1nc2(i1)+1\sum_{i=1}^n a_i \leq \sum_{i=1}^n c_{2(i-1)+1}

另一方面,令 (a1,b1)=(c1,c2),(a2,b2)=(c3,c4)(a_1, b_1) = (c_1, c_2), (a_2, b_2) = (c_3, c_4), ,(an,bn)=(c2n1\cdots, (a_n, b_n) = (c_{2n-1}, 此时每一组 (ai,bi)(a_i, b_i) 都满足 aibia_i \leq b_i 的要求,并且有 a1a2ana_1 \leq a_2 \leq \cdots \leq a_n,此时

i=1nai=i=1nc2(i1)+1\sum_{i=1}^n a_i = \sum_{i=1}^n c_{2(i-1)+1}

(2)(2) 式的等号是可满足的。因此所要求得的最大总和即为

i=1nc2(i1)+1\sum_{i=1}^n c_{2(i-1)+1}

代码

class Solution {
    func arrayPairSum(_ nums: [Int]) -> Int {
        var nums: [Int] = nums.sorted()
        var count: Int = nums.count
        var i: Int = 0
        var ans: Int = 0
        while i < count {
            ans += nums[i]
            i += 2
        }
        return ans
    }
}

复杂度分析

  • 时间复杂度:时间复杂度:O(nlogn)O(n\log n),即为对数组 nums\textit{nums} 进行排序的时间复杂度。

  • 空间复杂度:空间复杂度:O(logn)O(\log n),即为排序需要使用的栈空间。