LeetCode 888. 公平的糖果交换
题目描述


题意分析
Alice 和 Bob 各拿出一盒糖果交换,使交换后的糖果总量相等。返回两个盒子的糖果数量,顺序为 Alice、Bob,不是返回盒子的下标。题目保证至少存在一组答案,找到任意一组即可。
解法:总和差值 + 哈希集合
核心思路
[!blue]
设双方原总量为
sumA、sumB,Alice 换出x,Bob 换出y。交换后的总量分别为sumA - x + y和sumB - y + x,要求两者相等,整理得到2 * (x - y) = sumA - sumB。令
diff = (sumA - sumB) / 2,那么选定 Alice 的盒子x后,Bob 必须提供的数量唯一确定为y = x - diff。题目保证有整数答案,所以总量差一定是偶数,这里的整除不会丢失信息。将 Bob 所有盒子的数量存入哈希集合,再枚举 Alice 的每个盒子,查询对应的
y是否存在。命中时等式成立,交换一定可行;所有 Alice 盒子都被枚举,因此也不会漏掉题目保证存在的答案。每人只选择一盒,集合只需保存存在性,无需统计相同数量有几盒。
解题步骤
- 计算
sumA、sumB,同时把 Bob 的盒子数量加入集合。- 计算有正负号的半差
diff,不能取绝对值。- 依次取 Alice 的盒子数量
x,计算y = x - diff。- 若集合中存在
y,返回[x, y]。题目保证有解,合法输入一定会在枚举过程中返回。
代码实现
class Solution {
public int[] fairCandySwap(int[] aliceSizes, int[] bobSizes) {
int sumA = 0;
for (int size : aliceSizes) {
sumA += size;
}
int sumB = 0;
Set<Integer> bobSet = new HashSet<>();
for (int size : bobSizes) {
sumB += size;
bobSet.add(size);
}
// 交换同时改变两边总量,因此取总差的一半。
int diff = (sumA - sumB) / 2;
for (int size : aliceSizes) {
// 当前 Alice 盒子唯一对应的 Bob 盒子大小。
int target = size - diff;
if (bobSet.contains(target)) {
return new int[] {
size,
target
};
}
}
return new int[0];
}
}
func fairCandySwap(aliceSizes []int, bobSizes []int) []int {
sumA := 0
for _, size := range aliceSizes {
sumA += size
}
sumB := 0
bobSet := make(map[int]bool)
for _, size := range bobSizes {
sumB += size
bobSet[size] = true
}
// 交换同时改变两边总量,因此取总差的一半。
diff := (sumA - sumB) / 2
for _, size := range aliceSizes {
// 当前 Alice 盒子唯一对应的 Bob 盒子大小。
target := size - diff
if bobSet[target] {
return []int{
size,
target,
}
}
}
return []int{
}
}
复杂度分析
设 Alice、Bob 分别有
m、n盒糖果。
- 时间复杂度:期望 $O(m+n)$。求和、建集合和枚举各扫描一次数组,集合查询期望为 $O(1)$。
- 空间复杂度:$O(u_B)$,
u_B为 Bob 的不同盒子数量值的个数,最多为n。
关键点总结
[!green]
- 一次交换同时改变双方总量,总量差因此变化两倍,必须先除以 2。
- 平衡等式把两两枚举变成“固定一方,查询另一方唯一候选”。
- 相同大小的盒子只需在集合中出现一次,仍然足以提供一盒用于交换。
易错点总结
[!yellow]
diff定义为 Alice 总量减 Bob 总量的一半,对应候选必须是x - diff,不能反向相加。- 不能对总量差取绝对值,否则会丢失哪一方需要换出更多糖果的信息。
- 返回的是
[Alice 的数量, Bob 的数量],交换顺序或返回下标都不符合要求。
相似题目
| 题目 | 难度 | 关联与区别 |
|---|---|---|
| 面试题 16.21. 交换和 | 中等 | 等式化简相同,原题支持一般整数数组,本题元素是正糖果数量。 |
| 1. 两数之和 | 简单 | 固定一边数值后,交换平衡等式给出另一边唯一候选,可用哈希集合查询。 |
转载与许可
许可
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!