LeetCode~462. 最少移动次数使数组元素相等 II

119 阅读2分钟

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

题目描述

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

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

示例

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

提示

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

排序

要使得所有元素转化为相同元素,我们可以将数组进行排序,得到中间节点,两端往中间靠拢,统计所需的步骤。

class Solution {
    public int minMoves2(int[] nums) {
        // 排序
        Arrays.sort(nums);
        // 长度,中间点索引,结果
        int n = nums.length, mid = n / 2, res = 0;
        
        // 遍历数组
        for(int i = 0; i < mid; ++i){
            // 从左向中间靠拢
            res += Math.abs(nums[i] - nums[mid]);
            // 从右向中间靠拢
            res += Math.abs(nums[n - i - 1] - nums[mid]);
        }

        return res;
    }
}

快速选择

参考官方题解,利用快排的方式将目标数组进行排序,之后统计结果并返回。

class Solution {
    Random random = new Random();

    public int minMoves2(int[] nums) {
        int n = nums.length, x = quickSelect(nums, 0, n - 1, n / 2), ret = 0;
        for (int i = 0; i < n; ++i) {
            ret += Math.abs(nums[i] - x);
        }
        return ret;
    }

    public int quickSelect(int[] nums, int left, int right, int index) {
        int q = randomPartition(nums, left, right);
        if (q == index) {
            return nums[q];
        } else {
            return q < index ? quickSelect(nums, q + 1, right, index) : quickSelect(nums, left, q - 1, index);
        }
    }

    public int randomPartition(int[] nums, int left, int right) {
        int i = random.nextInt(right - left + 1) + left;
        swap(nums, i, right);
        return partition(nums, left, right);
    }

    public int partition(int[] nums, int left, int right) {
        int x = nums[right], i = left - 1;
        for (int j = left; j < right; ++j) {
            if (nums[j] <= x) {
                ++i;
                swap(nums, i, j);
            }
        }
        swap(nums, i + 1, right);
        return i + 1;
    }

    public void swap(int[] nums, int index1, int index2) {
        int temp = nums[index1];
        nums[index1] = nums[index2];
        nums[index2] = temp;
    }
}