题目
给你两个长度可能不等的整数数组 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 <= 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 0
diff=a-b #两者差距
def func(nums1,nums2,diff):
nums1.sort(reverse=True)
nums2.sort()
ans,m,n=0,len(nums1),len(nums2)
i=j=0
while i<m and j<n:
if nums1[i]-1>6-nums2[j]:
diff-=nums1[i]-1 #填平差距
i+=1
else:
diff-=6-nums2[j] #填平差距
j+=1
ans+=1 #记录操作次数
if diff<=0: #差距已被填平
return ans
if i!=m: #如果两个数组一长一短,进行后续的填平
for k in range(i,m):
diff-=nums1[k]-1
ans+=1
if diff<=0:
return ans
else:
for k in range(j,n):
diff-=6-nums2[k]
ans+=1
if diff<=0:
return ans
return -1
return func(nums1,nums2,diff) if a>b else func(nums2,nums1,-diff)