通过最少操作次数使数组的和相等
给你两个长度可能不等的整数数组 nums1 和 nums2 。两个数组中的所有值都在 1 到 6 之间(包含 1 和 6)。
每次操作中,你可以选择 任意 数组中的任意一个整数,将它变成 1 到 6 之间 任意 的值(包含 1 和 6)。
请你返回使 nums1 中所有数的和与 nums2 中所有数的和相等的最少操作次数。如果无法使两个数组的和相等,请返回 -1 。
- 总和较大的数组在每次操作中尽可能地减小,使较小的数组在每次操作中尽可能的增大
- 根据元素的贡献值,从大到小依次遍历,找出所需贡献值最少的操作次数。
/*
* Copyright (c) Huawei Technologies Co., Ltd. 2023-2023. All rights reserved.
*/
package com.huawei.prac;
import java.util.Arrays;
class Solution5th {
public static void main(String[] args) {
int[] nums1 = {1, 2, 3, 4, 5, 6};
int[] nums2 = {1, 1, 2, 2, 2, 2};
int[] nums12 = {1, 1, 1, 1, 1, 1, 1};
int[] nums22 = {6};
System.out.println(minOperations(nums1, nums2));
System.out.println(minOperations(nums12, nums22));
}
/**
* 【未解】1775. 通过最少操作次数使数组的和相等 【元素贡献值 + 向上取整】
* 总和较大的数组在每次操作中尽可能地减小,使较小的数组在每次操作中尽可能的增大
*
* @param nums1 数组S1
* @param nums2 数组S2
* @return 最少操作次数
*/
public static int minOperations(int[] nums1, int[] nums2) {
if (nums1.length * 6 < nums2.length || nums2.length * 6 < nums1.length) {
return -1;
}
int sumS1 = Arrays.stream(nums1).sum();
int sumS2 = Arrays.stream(nums2).sum();
if (sumS1 > sumS2) {
return getChangeNum(nums2, nums1);
}
return getChangeNum(nums1, nums2);
}
private static int getChangeNum(int[] nums1, int[] nums2) {
int[] contriVal = new int[6];
for (int num : nums1) {
contriVal[6 - num]++;
}
for (int num : nums2) {
contriVal[num - 1]++;
}
int difVal = Arrays.stream(nums2).sum() - Arrays.stream(nums1).sum();
int minOperaNum = 0;
for (int i = 5; i > 0; i--) {
if (difVal <= i * contriVal[i]) {
// 向上取整
return minOperaNum + (difVal + i - 1) / i;
}
minOperaNum += contriVal[i];
difVal -= i * contriVal[i];
}
return difVal;
}
}