来源:力扣(LeetCode)–NO.1775
链接:https://leetcode.cn/problems/equal-sum-arrays-with-minimum-number-of-operations
给你两个长度可能不等的整数数组 nums1 和 nums2 。两个数组中的所有值都在 1 到 6 之间(包含 1 和 6)。
每次操作中,你可以选择 任意 数组中的任意一个整数,将它变成 1 到 6 之间 任意 的值(包含 1 和 6)。
请你返回使 nums1 中所有数的和与 nums2 中所有数的和相等的最少操作次数。如果无法使两个数组的和相等,请返回 -1 。
1 <= nums1.length, nums2.length <= 105
1 <= nums1[i], nums2[i] <= 6
// 🎈本题使用贪心 + hashmap
class Solution {
public:
/*
help函数:辅助函数,用于增加h1所代表的数组sum,减小h2所代表的数组sum
目标:缩小diff直到其大于等于0(大于0也一定能缩小再等于零)
**在本题中,仅有(len1*6 < len2 || len2*6 < len1)这种情况返回-1**
*/
int help(vector<int> h1, vector<int> h2, diff) {
vector<int>contribute; // 计算每个数的贡献度
// 贡献度的目的是加起来能够抵消diff
// 大的减小,小的增加,计算贡献度
// 哈希表 👇
for(int i = 1; i < 7; ++i) {
h1[6-i] = h[i];
h2[i-1] = h[i];
}
int count = 0; // 定义计数器
// 贪心思想 👇
for(int i = 5; i && diff >= 0; --i){// 贡献度由高到低进行遍历
int t = min((diff+i-1)/i, h[i]);
//⭐ diff+i-1的作用是--- 使diff/i **向上取整**
count += t;
diff -= t*i; // 减去贡献度
}
}
int minOperations(vector<int>& nums1, vector<int>& nums2) {
vector<int>cnt1;
vector<int>cnt2;
int diff = 0;
int len1 = nums1.size();
int len2 = nums2.size();
// ⭐**在本题中,仅有(len1*6 < len2 || len2*6 < len1)这种情况返回-1**
if(len1*6 < len2 || len2*6 < len1) return -1;
for(int i = 0; i < len1; ++i) {
diff += nums1[i];
++cnt1[nums1[i]];
}
for(int i = 0; i < len2; ++i) {
diff -= nums2[i];
++cnt2[nums2[i]];
}
if(!diff) return 0;
// diff的正负并不重要
// ⭐本质是:增加nums1(nums2),减小nums2(nums1)以缩小diff
// diff>0 --> sum1 > sum2
if(diff > 0) return help(cnt2, cnt1, diff);
// diff<0 --> sum1 < sum2
return help(cnt1, cnt2, -diff); // 取diff的绝对值
}
};