力扣---6357. 使数组元素全部相等的最少操作次数

Posted allWu

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了力扣---6357. 使数组元素全部相等的最少操作次数相关的知识,希望对你有一定的参考价值。

给你一个正整数数组 nums 。
同时给你一个长度为 m 的整数数组 queries 。第 i 个查询中,你需要将 nums 中所有元素变成 queries[i] 。你可以执行以下操作 任意 次:
    将数组里一个元素 增大 或者 减小 1 。
请你返回一个长度为 m 的数组 answer ,其中 answer[i]是将 nums 中所有元素变成 queries[i] 的 最少 操作次数。
注意,每次查询后,数组变回最开始的值。

示例 1:
输入:nums = [3,1,6,8], queries = [1,5]
输出:[14,10]
解释:第一个查询,我们可以执行以下操作:
- 将 nums[0] 减小 2 次,nums = [1,1,6,8] 。
- 将 nums[2] 减小 5 次,nums = [1,1,1,8] 。
- 将 nums[3] 减小 7 次,nums = [1,1,1,1] 。
第一个查询的总操作次数为 2 + 5 + 7 = 14 。
第二个查询,我们可以执行以下操作:
- 将 nums[0] 增大 2 次,nums = [5,1,6,8] 。
- 将 nums[1] 增大 4 次,nums = [5,5,6,8] 。
- 将 nums[2] 减小 1 次,nums = [5,5,5,8] 。
- 将 nums[3] 减小 3 次,nums = [5,5,5,5] 。
第二个查询的总操作次数为 2 + 4 + 1 + 3 = 10 。

示例 2:
输入:nums = [2,9,6,3], queries = [10]
输出:[20]
解释:我们可以将数组中所有元素都增大到 10 ,总操作次数为 8 + 1 + 4 + 7 = 20 。

提示:
    n == nums.length
    m == queries.length
    1 <= n, m <= 105
    1 <= nums[i], queries[i] <= 109
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/minimum-operations-to-make-all-array-elements-equal
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

 从几十遍地写两数之和到现在周赛第三题磕磕绊绊独立写出来(虽然这次周赛我仍然是一名光荣的一题选手。。。),就挺感慨。

可以发现,实际上需要做的,是将nums中比x大的所有数全部减小为x,所有比x小的数全部增大为x。
即,我们只需要考虑两种:1:小于等于x的数。2:大于x的数。
很容易可以想到排序后利用二分查找来快速找到nums中x所在的位置。
再然后,可以想到利用额外空间来存储nums中,所有小于第i个元素的和以及所有大于第i个元素的和,这样可以把累加的时间复杂度降低到O(N)。

class Solution 
    public List<Long> minOperations(int[] nums, int[] queries) 
        // 存储答案
        List<Long> list = new ArrayList<>();
        int len = nums.length;
        // 存储第i个位置的前面的和(包括第i个),以及后面的和(不包括第i个)。
        long[][] sum = new long[len][2];
        // 排序
        Arrays.sort(nums);
        sum[0][0] = nums[0];
        // 所有小于等于第i个数字的和。
        for (int i = 1; i < len; i ++) 
            sum[i][0] = sum[i - 1][0] + nums[i];
        
        // 所有大于第i个数字的和。
        for (int i = len - 2; i >= 0; i --) 
            sum[i][1] = sum[i + 1][1] + nums[i + 1];
        
        for (int x : queries) 
            int index = search(nums, x);
            long res;
            // 如果index < 0,则说明nums中所有元素都比x大。
            if (index < 0) 
                res = sum[len - 1][0] - (long) x * len;
             else 
                // 结果的和即是所有比x小的数增成x,所有比x大的数减成x
                res = (long) x * (index + 1) - sum[index][0] + sum[index][1] - (long) x * (len - index - 1);
            
            list.add(res);
        
        return list;
    
    // 二分查找,找到x在nums中的位置,如果nums中不包括x,则返回比x小的数的下标(如果所有元素都比x大,则返回-1)
    private int search(int[] nums, int x) 
        int left = 0;
        int right = nums.length - 1;
        while (left < right) 
            int mid = (left + right) / 2;
            if (nums[mid] < x) 
                left = mid + 1;
             else if (nums[mid] > x) 
                right = mid -1;
             else 
                return mid;
            
        
        return nums[left] > x ? left - 1 : left;
    

 

以上是关于力扣---6357. 使数组元素全部相等的最少操作次数的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode 1775. 通过最少操作次数使数组的和相等

一道题,最小操作次数使数组元素相等引发的思考

一道题,最小操作次数使数组元素相等引发的思考

一道题,最小操作次数使数组元素相等引发的思考

Leetcode 462.最少移动次数使数组元素相等

453. 最小移动次数使数组元素相等(数学)