本文最后更新于:2024年6月7日 中午
前言
本题出自Leetcode
周赛 369场
原题链接2918.数组的最小相等和
本题不需要任何算法 一个纯分类讨论题目
题目描述
给你两个由正整数和 0
组成的数组 nums1
和 nums2
。
你必须将两个数组中的 所有 0
替换为 严格 正整数,并且满足两个数组中所有元素的和 相等 。
返回 最小 相等和 ,如果无法使两数组相等,则返回 -1
。
1 2 3 4 5 6 7 8 9 10 11 12 示例 1: 输入:nums1 = [3,2,0,1,0], nums2 = [6,5,0] 输出:12 解释:可以按下述方式替换数组中的 0 : - 用 2 和 4 替换 nums1 中的两个 0 。得到 nums1 = [3,2,2,1,4] 。 - 用 1 替换 nums2 中的一个 0 。得到 nums2 = [6,5,1] 。 两个数组的元素和相等,都等于 12 。可以证明这是可以获得的最小相等和。 示例 2: 输入:nums1 = [2,0,2,0], nums2 = [1,4] 输出:-1 解释:无法使两个数组的和相等。
数据范围
1 <= nums1.length, nums2.length <= 105
0 <= nums1[i], nums2[i] <= 106
解题思路
我们可以分成五种 情况讨论
假设数组的和相等
假设nums1
有0 nums2
没0
假设nums1
没0 nums2
有0
两个数组都有0
两个数组都没0
先来看看第一种情况 如果两个数组和相等 我们需要判断nums1不包含0 == nums2不包含0
,如果符合条件则直接返回任意一个数组和
第二种情况 设i = n u m s 2 [ n ] + n u m s 2 [ n + 1 ] + n u m s 2 [ n + 2 ] . . . . i=nums2[n]+nums2[n+1]+nums2[n+2].... i = n u m s 2 [ n ] + n u m s 2 [ n + 1 ] + n u m s 2 [ n + 2 ] .... ,j j j 为n u m s 1 nums1 n u m s 1 数组中的0个数,k = n u m s 1 [ n ] + n u m s 1 [ n + 1 ] . . . . k=nums1[n]+nums1[n+1].... k = n u m s 1 [ n ] + n u m s 1 [ n + 1 ] .... 如果k > = i ∣ ( i − k ) / / j = = 0 k>=i\mid(i-k)//j==0 k >= i ∣ ( i − k ) // j == 0 则返回− 1 -1 − 1 ,否返回n u m s 2 nums2 n u m s 2 的数组和
第三种情况 设i = n u m s 1 [ n ] + n u m s 1 [ n + 1 ] + n u m s 1 [ n + 2 ] . . . . i=nums1[n]+nums1[n+1]+nums1[n+2].... i = n u m s 1 [ n ] + n u m s 1 [ n + 1 ] + n u m s 1 [ n + 2 ] .... ,j j j 为n u m s 2 nums2 n u m s 2 数组中的0个数,k = n u m s 2 [ n ] + n u m s 2 [ n + 1 ] . . . . k=nums2[n]+nums2[n+1].... k = n u m s 2 [ n ] + n u m s 2 [ n + 1 ] .... 如果k > = i ∣ ( i − k ) / / j = = 0 k>=i\mid(i-k)//j==0 k >= i ∣ ( i − k ) // j == 0 则返回− 1 -1 − 1 ,否返回n u m s 1 nums1 n u m s 1 的数组和
关于这条公式的到来 我这里解释一下
假设 n u m s 1 = [ 3 , 2 , 0 , 1 , 0 ] , n u m s 2 = [ 6 , 5 , 1 ] nums1 = [3,2,0,1,0], nums2 = [6,5,1] n u m s 1 = [ 3 , 2 , 0 , 1 , 0 ] , n u m s 2 = [ 6 , 5 , 1 ] 可以看到第二个数组是没0的 第一个有两个零
第一个条件 k > = i k>=i k >= i 则说明 如果第一个数组还是0的情况 它的和已经大于第二个数组 显然是无法修改的 只能返回-1
在满足第一个条件之下 我们还要继续判断 ( i − k ) / / j (i-k)//j ( i − k ) // j 意思是 求出两个数组的差 然后除于第一个数组的0的个数 校验一下是否能把第一个数组的所有0均匀分配 如果除出来是0说明第一个数组和第二个数组的和无法相等
第四种情况 先把n u m s 1 nums1 n u m s 1 的0 全部改成1 代入第二种情况 再反过来重复即可
注意:第四种情况 如果无法满足条件 不要返回-1 而是原始的答案 具体看下面的代码
第五种情况 直接判断和是否相等 相等返回其中一个n u m s nums n u m s 的和 没则返回**-1**
现在看看代码怎么写
首先定义四个函数i,j,i_,j_
i i i 是n u m s 1 nums1 n u m s 1 的和
j j j 是n u m s 2 nums2 n u m s 2 的和
i _ i\_ i _ 是n u m s 1 nums1 n u m s 1 0 的个数
j _ j\_ j _ 是n u m s 2 nums2 n u m s 2 0 的个数
1 2 3 4 5 6 7 8 9 class Solution : def minSum (self, nums1: List [int ], nums2: List [int ] ) -> int : i,j,i_,j_ = sum (nums1),sum (nums2),0 ,0 for k in range (0 ,len (nums1)): if nums1[k] == 0 : i_+=1 for k in range (0 ,len (nums2)): if nums2[k] == 0 : j_+=1
先来判断第一种情况和最后一种情况
1 2 3 4 5 6 7 8 9 10 11 12 13 class Solution : def minSum (self, nums1: List [int ], nums2: List [int ] ) -> int : i,j,i_,j_ = sum (nums1),sum (nums2),0 ,0 for k in range (0 ,len (nums1)): if nums1[k] == 0 : i_+=1 for k in range (0 ,len (nums2)): if nums2[k] == 0 : j_+=1 if i == j and i_ == 0 and j_ == 0 : return i if i_ == 0 and j_ == 0 : return i == j
这里不能压缩两种情况,假设两个数组的数相同,左边没0右边有0,这种情况不适合
分别写入第二种情况和第三种情况
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Solution : def minSum (self, nums1: List [int ], nums2: List [int ] ) -> int : i,j,i_,j_ = sum (nums1),sum (nums2),0 ,0 for k in range (0 ,len (nums1)): if nums1[k] == 0 : i_+=1 for k in range (0 ,len (nums2)): if nums2[k] == 0 : j_+=1 if i == j and i_ == 0 and j_ == 0 : return i if i_ == 0 and j_ == 0 : return -1 if i != j else i if i_ == 0 and j_ != 0 : return -1 if j >= i or (i-j)//j_ == 0 else i if i_ != 0 and j_ == 0 : return -1 if i >= j or (j-i)//i_ == 0 else j
最后写第四种情况,定义ans
为最终答案 并把ans
初始化成10的11次方
先填充nums1
然后代入公式 更新最小值 nums2
同理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class Solution : def minSum (self, nums1: List [int ], nums2: List [int ] ) -> int : i,j,i_,j_ = sum (nums1),sum (nums2),0 ,0 for k in range (0 ,len (nums1)): if nums1[k] == 0 : i_+=1 for k in range (0 ,len (nums2)): if nums2[k] == 0 : j_+=1 if i == j and i_ == 0 and j_ == 0 : return i if i_ == 0 and j_ == 0 : return -1 if i != j else i if i_ == 0 and j_ != 0 : return -1 if j >= i or (i-j)//j_ == 0 else i if i_ != 0 and j_ == 0 : return -1 if i >= j or (j-i)//i_ == 0 else j o = 10 ** 11 for k in range (0 ,len (nums1)): if nums1[k] == 0 : nums1[k] = 1 k_ = sum (nums1) o = min (o,o if j >= k_ or (k_-j)//j_ == 0 else k_) for k in range (0 ,len (nums2)): if nums2[k] == 0 : nums2[k] = 1 k_ = sum (nums2) o = min (o,o if i >= k_ or (k_-i)//i_ == 0 else k_) return o
示例代码
Python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class Solution : def minSum (self, nums1: List [int ], nums2: List [int ] ) -> int : i,j,i_,j_ = sum (nums1),sum (nums2),0 ,0 for k in range (0 ,len (nums1)): if nums1[k] == 0 : i_+=1 for k in range (0 ,len (nums2)): if nums2[k] == 0 : j_+=1 if i == j and i_ == 0 and j_ == 0 : return i if i_ == 0 and j_ == 0 : return -1 if i != j else i if i_ == 0 and j_ != 0 : return -1 if j >= i or (i-j)//j_ == 0 else i if i_ != 0 and j_ == 0 : return -1 if i >= j or (j-i)//i_ == 0 else j o = 10 ** 11 for k in range (0 ,len (nums1)): if nums1[k] == 0 : nums1[k] = 1 k_ = sum (nums1) o = min (o,o if j >= k_ or (k_-j)//j_ == 0 else k_) for k in range (0 ,len (nums2)): if nums2[k] == 0 : nums2[k] = 1 k_ = sum (nums2) o = min (o,o if i >= k_ or (k_-i)//i_ == 0 else k_) return o
C++
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class Solution {public : long long minSum (vector<int >& nums1, vector<int >& nums2) { long long i = 0 ; long long j = 0 ; int i_ = 0 ; int j_ = 0 ; for (int k = 0 ; k < nums1.size (); k++ ){ if (nums1[k] == 0 ){i_++;}else {i+=nums1[k];} } for (int k = 0 ; k < nums2.size (); k++){ if (nums2[k] == 0 ){j_++;}else {j+=nums2[k];} } if (i == j && i_ == 0 && j_ == 0 ){return i;} if (i_ == 0 && j_ == 0 ){return i = j ? -1 : i;} if (i_ == 0 && j_ != 0 ){return j >= i || (i-j)/j_ == 0 ? -1 : i;} if (i_ != 0 && j_ == 0 ){return i >= j || (j-i)/i_ == 0 ? -1 : j;} long long o = 100000000000 ; long long k_ = 0 ; for (int k = 0 ; k < nums1.size (); k++){ if (nums1[k]==0 ){nums1[k] = 1 ;k_++;}else {k_+=nums1[k];} } o = min (o,j >= k_ || (k_-j)/j_ == 0 ? o : k_); k_ = 0 ; for (int k = 0 ; k < nums2.size (); k++){ if (nums2[k]==0 ){nums2[k] = 1 ; k_++;}else {k_+=nums2[k];} } o = min (o,i >= k_ || (k_-i)/i_ == 0 ? o : k_); if (o == 100000000000 ){return -1 ;} return o; } };
后记
这种题写起来真麻烦 博主测试的时候错了很多次
感谢你的收看