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

64 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第12天,点击查看活动详情

题目描述

给你两个长度可能不等的整数数组 nums1 和 nums2 。两个数组中的所有值都在 1 到 6 之间(包含 1 和 6)。

每次操作中,你可以选择 任意 数组中的任意一个整数,将它变成 1 到 6 之间 任意 的值(包含 1 和 6)。

请你返回使 nums1 中所有数的和与 nums2 中所有数的和相等的最少操作次数。如果无法使两个数组的和相等,请返回 -1 。

示例 1:

输入: nums1 = [1,2,3,4,5,6], nums2 = [1,1,2,2,2,2]
输出: 3
解释: 你可以通过 3 次操作使 nums1 中所有数的和与 nums2 中所有数的和相等。以下数组下标都从 0 开始。
- 将 nums2[0] 变为 6 。 nums1 = [1,2,3,4,5,6], nums2 = [6,1,2,2,2,2] 。
- 将 nums1[5] 变为 1 。 nums1 = [1,2,3,4,5,1], nums2 = [6,1,2,2,2,2] 。
- 将 nums1[2] 变为 2 。 nums1 = [1,2,2,4,5,1], nums2 = [6,1,2,2,2,2]

示例 2:

输入: nums1 = [1,1,1,1,1,1,1], nums2 = [6]
输出: -1
解释: 没有办法减少 nums1 的和或者增加 nums2 的和使二者相等。

示例 3:

输入: nums1 = [6,6], nums2 = [1]
输出: 3
解释: 你可以通过 3 次操作使 nums1 中所有数的和与 nums2 中所有数的和相等。以下数组下标都从 0 开始。
- 将 nums1[0] 变为 2 。 nums1 = [2,6], nums2 = [1] 。
- 将 nums1[1] 变为 2 。 nums1 = [2,2], nums2 = [1] 。
- 将 nums2[0] 变为 4 。 nums1 = [2,2], nums2 = [4]

提示:

  • 1 <= nums1.length, nums2.length <= 105
  • 1 <= nums1[i], nums2[i] <= 6

思路分析

题目会给我们两个数组,我们每次可以选择两个数组中的任一元素变为1 到 6 之间 任意 的值(包含 1 和 6),要求我们计算出将两数组的元素和变为相等需要进行多少次操作,我们可以先计算出两个数组的元素和,元素和大的那个数组肯定是要将元素值缩小,另一个则是要将值变大,我们只需要判断每次进行修改的时候那个数组进行修改的性价比更高即可。

  • 1、计算两数组元素和

分别计算两个数组的元素和

let sum1 = 0,sum2 = 0;
for(let i = 0; i < nums1.length; i++) sum1 += nums1[i];
for(let i = 0; i < nums2.length; i++) sum2 += nums2[i];
  • 2、对数组进行排序

元素和较大的数组按大到小排序,元数和小的则按从小到大排序。

if(sum1 < sum2){
    [sum1,sum2] = [sum2,sum1];
    [nums1, nums2] = [nums2, nums1];
}
nums1 = nums1.sort((a,b)=>{
    return b- a;
});
nums2 = nums2.sort((a,b)=>{
    return a - b;
});
  • 3、计算操作数

因为我们已经排过序,假设数组1为元素和较大的数组,我们则需要将其元素变小,因为数组1是从大到小排序的,所以从我们可以从前往后进行改变。判断将数组1的元素改为6与将数组2的元素改为1这两种操作的收益,选择收益更高的做法,当进行修改后两数组的元素和可以相等时即可得到答案。

let i = 0,j = 0;
while(i < nums1.length || j < nums2.length){
    if(nums1[i] - 1 > 6 - nums2[j] || j >= nums2.length){
        sum1 -= (nums1[i++] - 1);
    }else{
        sum2 += (6 - nums2[j++]);
    }
    if(sum1 <= sum2){
        return (i + j);
    }
}

AC代码

完整AC代码如下:

/**
 * @param {number[]} nums1
 * @param {number[]} nums2
 * @return {number}
 */
var minOperations = function(nums1, nums2) {
    let sum1 = 0,sum2 = 0;
    for(let i = 0; i < nums1.length; i++) sum1 += nums1[i];
    for(let i = 0; i < nums2.length; i++) sum2 += nums2[i];
    if(sum1 == sum2) return 0;
    if(sum1 < sum2){
        [sum1,sum2] = [sum2,sum1];
        [nums1, nums2] = [nums2, nums1];
    }
    nums1 = nums1.sort((a,b)=>{
        return b- a;
    });
    nums2 = nums2.sort((a,b)=>{
        return a - b;
    });
    let i = 0,j = 0;
    while(i < nums1.length || j < nums2.length){
        if(nums1[i] - 1 > 6 - nums2[j] || j >= nums2.length){
            sum1 -= (nums1[i++] - 1);
        }else{
            sum2 += (6 - nums2[j++]);
        }
        if(sum1 <= sum2){
            return (i + j);
        }
    }
    return -1;
};

说在后面

本人为算法业余爱好者,平时只是随着兴趣偶尔刷刷题,如果上面分享有错误的地方,欢迎指出,感激不尽。