LeetCode 462. 最小操作次数使数组元素相等 II

462. 最小操作次数使数组元素相等 II

给你一个长度为 n 的整数数组 nums ,返回使所有数组元素相等需要的最小操作数。

在一次操作中,你可以使数组中的一个元素加 1 或者减 1 。

测试用例经过设计以使答案在 32 位 整数范围内。

示例 1:

输入:nums = [1,2,3]
输出:2
解释:
只需要两次操作(每次操作指南使一个元素加 1 或减 1):
[1,2,3]  =>  [2,2,3]  =>  [2,2,2]

示例 2:

输入:nums = [1,10,2,9]
输出:16

提示:

  • n == nums.length
  • 1 <= nums.length <= 10^5
  • -10^9 <= nums[i] <= 10^9

解法1:排序


假设数组元素都变成 x 时,所需的移动数最少,那么 x 需要满足什么性质呢?

为了简化讨论,我们先假定数组长度 n 是偶数。我们将数组 nums 从小到大进行排序,然后将数组进行首尾配对,从而划分为多个数对,并将这些数对组成区间:

当 x 同时位于以上区间内时,所需的移动数最少,总移动数为 

证明:对于某一个区间 [nums[i]​ ,nums[n−1−i] ​],该区间对应的数对所需要的移动数为

∣nums[n−1−i] ​−x∣+∣nums[i]​ −x∣≥∣nums[n−1−i]​ −x−(nums[i]​ −x)∣=nums[n−1−i]​ −nums[i]​ ,当且仅当 x∈[nums[i]​ ,nums[n−1−i]​ ] 时,等号成立。 

在上述区间中,后一个区间是前一个区间的子集,因此只要 x∈[nums[n/2−1] ​,nums[n/2]  ],就满足要求。

当 n 为奇数时,我们将排序后的数组中间的元素 nums[n/2] ​ 当成区间 [nums[n/2] ​,nums[n/2] ​] 看待,则 x∈[nums[n/2] ​, nums[n/2] ​] 即 x=nums[n/2] ​时,所需的移动数最少。 

综上所述,所有元素都变成 nums[n/2] 时,所需的移动数最少。

Java版:

class Solution {
    public int minMoves2(int[] nums) {
        Arrays.sort(nums);
        int n = nums.length;
        int mid = (n - 1) / 2;
        int ans = 0;
        for (int i = 0; i < n; i++) {
            if (i < mid) {
                ans += nums[mid] - nums[i];
            } else {
                ans += nums[i] - nums[mid];
            }
        }
        return ans;
    }
}

class Solution {
    public int minMoves2(int[] nums) {
        Arrays.sort(nums);
        int n = nums.length;
        int mid = n / 2;
        int ans = 0;
        for (int i = 0; i < n; i++) {
            if (i < mid) {
                ans += nums[mid] - nums[i];
            } else {
                ans += nums[i] - nums[mid];
            }
        }
        return ans;
    }
}

Python3版:

class Solution:
    def minMoves2(self, nums: List[int]) -> int:
        nums.sort()
        n = len(nums)
        mid = (n - 1) // 2
        ans = 0
        for i in range(n):
            if i < mid:
                ans += nums[mid] - nums[i]
            else:
                ans += nums[i] - nums[mid]
        return ans

class Solution:
    def minMoves2(self, nums: List[int]) -> int:
        nums.sort()
        n = len(nums)
        mid = n // 2
        ans = 0
        for i in range(n):
            if i < mid:
                ans += nums[mid] - nums[i]
            else:
                ans += nums[i] - nums[mid]
        return ans

复杂度分析

  • 时间复杂度:O(nlogn),其中 n 是数组 nums 的长度。排序需要 O(nlogn) 的时间。
  • 空间复杂度:O(logn)。排序需要 O(logn) 的递归栈空间。
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值