【刷题打卡】888. 公平的糖果交换

163 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

一、题目描述:

888. 公平的糖果交换

爱丽丝和鲍勃拥有不同总数量的糖果。给你两个数组 aliceSizesbobSizesaliceSizes[i] 是爱丽丝拥有的第 i 盒糖果中的糖果数量,bobSizes[j] 是鲍勃拥有的第 j 盒糖果中的糖果数量。

两人想要互相交换一盒糖果,这样在交换之后,他们就可以拥有相同总数量的糖果。一个人拥有的糖果总数量是他们每盒糖果数量的总和。

返回一个整数数组 answer,其中 answer[0] 是爱丽丝必须交换的糖果盒中的糖果的数目,answer[1] 是鲍勃必须交换的糖果盒中的糖果的数目。如果存在多个答案,你可以返回其中 任何一个 。题目测试用例保证存在与输入对应的答案。

 

示例 1:

输入:aliceSizes = [1,1], bobSizes = [2,2]
输出:[1,2]

示例 2:

输入:aliceSizes = [1,2], bobSizes = [2,3]
输出:[1,2]

示例 3:

输入:aliceSizes = [2], bobSizes = [1,3]
输出:[2,3]

示例 4:

输入:aliceSizes = [1,2,5], bobSizes = [2,4]
输出:[5,4]

提示:

  • 1 <= aliceSizes.length, bobSizes.length <= 10^4
  • 1 <= aliceSizes[i], bobSizes[j] <= 10^5
  • 爱丽丝和鲍勃的糖果总数量不同。
  • 题目数据保证对于给定的输入至少存在一个有效答案。

二、思路分析:

先分别求出Alice 和 Bob 手里糖果棒的总量, 分别记为sumA 和 sumB。 如果Alice 把第i个糖果棒给Bob, Bob 用第j个糖果棒和Alice换, 按照题意, 需要找到 A[i] 和 B[j] 使得以下等式成立:

sumA - A[i] + B[j] = sumB - B[j] + A[i]

原始的思路是暴力求解: 对于每一个A[i], 遍历所有的B[j]来求解, 但是会超时。 后来想到题目问的是交换糖果的大小, 不考虑顺序, 就尝试用二分法优化了一下查找B[j]的过程。这样一来就能通过所有测试了。

三、AC 代码:

class Solution {
public:
    vector<int> fairCandySwap(vector<int>& A, vector<int>& B) {
        int sumA = 0, sumB = 0;

        // 求Alice数组的和
        for (int a = 0; a < A.size(); a++) {
            sumA += A[a];
        }

        // 求Bob数组的和
        for (int b = 0; b < B.size(); b++) {
            sumB += B[b];
        }

        vector<int> result(2, 0);
        int left = 0, right = B.size() - 1;
        int midb = left + (right - left)/2;

        //对两个数组排序
        sort(A.begin(), A.end());
        sort(B.begin(), B.end());

        for (int i = 0; i < A.size(); i++) {
            // 找到Alice给出第i个糖果之后所剩的糖果大小的和
            int newSumA = sumA - A[i]; 
            left = 0; 
            right = B.size() - 1;

            // 用二分法找Bob 要交换的糖果大小
            while (left <= right && left >= 0 && right >= 0) {
                midb =  left + (right - left)/2;
                int newSumB = sumB - B[midb];

                // Bob 需要找小一些的糖果
                if (newSumA + B[midb] > newSumB + A[i]) {
                    right = midb - 1;

                // Bob 需要找大一些的糖果大小
                }else if (newSumA + B[midb] < newSumB + A[i]) {
                    left = midb + 1;

                // 正好找到了合适的糖果大小
                // 存起来
                }else {
                    result[0] = A[i];
                    result[1] = B[midb];
                    return result;
                }
            }
        }

        return result;
    }
};