题目来源:力扣(LeetCode)https://leetcode-cn.com/problems/fair-candy-swap/
爱丽丝和鲍勃有不同大小的糖果棒:A[i]
是爱丽丝拥有的第 i
根糖果棒的大小,B[j]
是鲍勃拥有的第 j
根糖果棒的大小。
因为他们是朋友,所以他们想交换一根糖果棒,这样交换后,他们都有相同的糖果总量。(一个人拥有的糖果总量是他们拥有的糖果棒大小的总和。)
返回一个整数数组 ans
,其中 ans[0]
是爱丽丝必须交换的糖果棒的大小,ans[1]
是 Bob 必须交换的糖果棒的大小。
如果有多个答案,你可以返回其中任何一个。保证答案存在。
示例 1:
输入:A = [1,1], B = [2,2]
输出:[1,2]
示例 2:
输入:A = [1,2], B = [2,3]
输出:[1,2]
示例 3:
输入:A = [2], B = [1,3]
输出:[2,3]
示例 4:
输入:A = [1,2,5], B = [2,4]
输出:[5,4]
提示:
1 <= A.length <= 10000
1 <= B.length <= 10000
1 <= A[i] <= 100000
1 <= B[i] <= 100000
这里,先看题目最后的提示部分,【保证爱丽丝与鲍勃的糖果总量不同】和【答案肯定存在】,即是说题目一定有解,要使得两人手中糖果总量相等,必然存在要交换的情况。
题目最后提醒,若存在多个答案时,返回其中一个即可。所以我们在查找的过程中,只要找到符合条件的情形,即可返回结果。
现在先审题,注意其中的参数:
题目设定:
糖果总量:指手中糖果棒大小的总和。
最终题目所求:
首先,我们先注意交换后的结果,两人手中最终的糖果总量是相等的。
假设 s u m _ A sum\_A sum_A 为 A l i c e Alice Alice 原本手中糖果总量, s u m _ B sum\_B sum_B 表示 B o b Bob Bob 原本手中糖果总量。而 a a a 表示 A l i c e Alice Alice 交换出去的糖果棒大小, b b b 表示 B o b Bob Bob 交换出去的糖果棒大小。因为最终交换后,两人的糖果总量是相等的,那么就有如下等式:
s u m _ A − a + b = s u m _ B − b + a sum\_A - a + b = sum\_B - b + a sum_A−a+b=sum_B−b+a
进行简化:
s u m _ A − a + b = s u m _ B − b + a 2 × a = s u m _ A − s u m _ B + 2 × b a = ( s u m _ A − s u m _ B ) 2 + b \begin{aligned} sum\_A - a + b & = sum\_B - b + a \\ 2 \times a & = sum\_A - sum\_B + 2 \times b \\ a &= \frac{(sum\_A - sum\_B)}{2} + b \end{aligned} sum_A−a+b2×aa=sum_B−b+a=sum_A−sum_B+2×b=2(sum_A−sum_B)+b
令 d e l t a = ( s u m _ A − s u m _ B ) 2 delta = \frac{(sum\_A - sum\_B)}{2} delta=2(sum_A−sum_B),那么
当数组 B B B 中存在一个数 b b b,使得 b + d e l t a b + delta b+delta 的和 a a a 存在于数组 A A A 中,那么此时 [ a , b ] [a, b] [a,b] 就是一组解。
因为需要查找 a a a 是否存在于 A A A 中,这里将数组 A A A 的元素存入哈希表中。然后遍历数组 B B B,将每个元素代入上面等式,检查 a a a 是否存在于 A A A 中。
具体的代码实现如下。
class Solution:
def fairCandySwap(self, A: List[int], B: List[int]) -> List[int]:
# 先求 A、B 的总量
sum_A = sum(A)
sum_B = sum(B)
# 根据文章得到的公式,先求 delta
delta = (sum_A - sum_B) // 2
# 将数组 A 元素存入哈希表
A = set(A)
# 遍历 B,进行查找
for b in B:
a = b + delta
if a in A:
return [a, b]
公众号 【书所集录】
如有错误,烦请指出,欢迎指点交流。若觉得写得还不错,麻烦点个赞,谢谢。