通过最少操作次数使数组的和相等
难度:
标签:
题目描述
代码结果
运行时间: 68 ms, 内存: 20.6 MB
/*
* 思路:
* 1. 计算两个数组的和,确定哪个数组的和更大,计算出需要调整的差值。
* 2. 使用一个数组记录可以通过每个元素的变换(增加或者减少)来获得的变化量。
* 3. 对变化量进行排序,从最大的变化量开始,逐个应用变化量,直到达到目标差值。
* 4. 返回最少的操作次数,如果无法达到目标差值,返回-1。
*/
import java.util.Arrays;
public class Solution {
public int minOperations(int[] nums1, int[] nums2) {
int sum1 = Arrays.stream(nums1).sum();
int sum2 = Arrays.stream(nums2).sum();
if (sum1 == sum2) return 0;
if (sum1 > sum2) return minOperationsHelper(nums1, nums2, sum1 - sum2);
else return minOperationsHelper(nums2, nums1, sum2 - sum1);
}
private int minOperationsHelper(int[] larger, int[] smaller, int diff) {
int[] changes = Arrays.stream(larger).map(num -> num - 1)
.boxed()
.sorted((a, b) -> b - a)
.mapToInt(Integer::intValue)
.toArray();
changes = Arrays.copyOf(changes, changes.length + smaller.length);
int index = larger.length;
for (int num : smaller) changes[index++] = 6 - num;
Arrays.sort(changes);
int operations = 0;
for (int i = changes.length - 1; i >= 0 && diff > 0; i--) {
diff -= changes[i];
operations++;
}
return diff > 0 ? -1 : operations;
}
}
解释
方法:
首先计算两个数组的和,如果一个数组的和大于另一个数组,将它们交换,以便始终让a是较小的和。然后检查是否有可能通过修改使两个数组和相等,即检查数组长度的6倍是否大于另一个数组的长度,如果是则返回-1。使用Counter来计数每个数组中各数字的出现次数。然后计算两数组和之差de。通过从1到6遍历,尝试减少这个差距。对于每个数字i,计算可以通过将nums1中的i增加到6或将nums2中的7-i减少到1来改变差距的总次数。如果通过当前数字能够完全消除差距,则直接返回结果;如果不能,则减少差距并继续处理。这个过程中,ans累加操作次数,直到差距为0。
时间复杂度:
O(n + m)
空间复杂度:
O(1)
代码细节讲解
🦆
为什么在判断两个数组和是否可以通过修改变得相等时,需要检查数组长度的6倍是否大于另一个数组的长度?
▷🦆
在算法中,`ceil(de / (6 - i))`的计算方法为何能确保最小操作次数,这里的逻辑是怎样的?
▷🦆
为什么选择从1到6遍历数字,并计算通过增加或减少来改变差距的次数,这样的策略为何是高效的?
▷