给你两个长度可能不等的整数数组 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 开始。
输入:nums1 = [1,1,1,1,1,1,1], nums2 = [6]
输出:-1
解释:没有办法减少 nums1 的和或者增加 nums2 的和使二者相等。
示例 3:
输入:nums1 = [6,6], nums2 = [1]
输出:3
解释:你可以通过 3 次操作使 nums1 中所有数的和与 nums2 中所有数的和相等。以下数组下标都从 0 开始。
提示:
1 <= nums1.length, nums2.length <= 10^5
1 <= nums1[i], nums2[i] <= 6
来源:力扣(LeetCode)
这个题和归并排序中将两个归并段归并有些许类似。首先需要定义操作,所要用到的操作无非就是两种,第一种就是将当前的数字减到1,第二种就是将当前的数字加到6,如果nums1的和大于nums2的和,那么对于nums1里的元素一定是做减法的,对于nums2中的元素一定是做加法,怎么操作收益最大?这是很显然的,如果一个数字尽可能的大然后是需要做减法的,那么它的收益是最大的,如果一个数字尽可能的小然后需要做加法,那么它的收益是最大的,所以我们需要先对nums1和nums2进行排序,一个按降序来排,一个按升序排,排完之后定义两个指针,分别指向两个数组的头部并按条件进行遍历,到了这里就开始有些像归并段的合并了,分别判断i指向的元素和j指向的元素哪个收益最大,即判断,i指向的元素减去1和6减去j指向的元素哪个大,哪种操作收益大就选择哪种操作,并且进行差距的填平,如果遍历完两个数组都没能将两者的差距填平,那么返回-1。
class Solution:def minOperations(self, nums1: List[int], nums2: List[int]) -> int:a,b=sum(nums1),sum(nums2)if a==b:return 0diff=a-b #两者差距def func(nums1,nums2,diff):nums1.sort(reverse=True)nums2.sort()ans,m,n=0,len(nums1),len(nums2)i=j=0while i6-nums2[j]:diff-=nums1[i]-1 #填平差距i+=1else:diff-=6-nums2[j] #填平差距j+=1ans+=1 #记录操作次数if diff<=0: #差距已被填平return ansif i!=m: #如果两个数组一长一短,进行后续的填平for k in range(i,m):diff-=nums1[k]-1ans+=1if diff<=0:return anselse:for k in range(j,n):diff-=6-nums2[k]ans+=1if diff<=0:return ansreturn -1return func(nums1,nums2,diff) if a>b else func(nums2,nums1,-diff)