888. 公平的糖果交换

爱丽丝和鲍勃拥有不同总数量的糖果。给你两个数组 aliceSizes 和 bobSizes ,aliceSizes[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 <= 104
    1 <= aliceSizes[i], bobSizes[j] <= 105
    爱丽丝和鲍勃的糖果总数量不同。
    题目数据保证对于给定的输入至少存在一个有效答案。

方法一:哈希表

思路及算法

记爱丽丝的糖果棒的总大小为 sumA\textit{sumA}sumA,鲍勃的糖果棒的总大小为 sumB\textit{sumB}sumB。设答案为 {x,y}\{x,y\}{x,y},即爱丽丝的大小为 xxx 的糖果棒与鲍勃的大小为 yyy 的糖果棒交换,则有如下等式:

sumA−x+y=sumB+x−y\textit{sumA} - x + y = \textit{sumB} + x - y sumA−x+y=sumB+x−y

化简,得:

x=y+sumA−sumB2x = y + \frac{\textit{sumA} - \textit{sumB}}{2} x=y+2sumA−sumB​

即对于 bobSizes\textit{bobSizes}bobSizes 中的任意一个数 y′y'y′,只要 aliceSizes\textit{aliceSizes}aliceSizes 中存在一个数 x′x'x′,满足 x′=y′+sumA−sumB2x' = y' + \dfrac{\textit{sumA} - \textit{sumB}}{2}x′=y′+2sumA−sumB​,那么 {x′,y′}\{x',y'\}{x′,y′} 即为一组可行解。

为了快速查询 aliceSizes\textit{aliceSizes}aliceSizes 中是否存在某个数,我们可以先将 aliceSizes\textit{aliceSizes}aliceSizes 中的数字存入哈希表中。然后遍历 bobSizes\textit{bobSizes}bobSizes 序列中的数 y′y'y′,在哈希表中查询是否有对应的 x′x'x′。

class Solution {
    public int[] fairCandySwap(int[] aliceSizes, int[] bobSizes) {
        int sumA = Arrays.stream(aliceSizes).sum();
        int sumB = Arrays.stream(bobSizes).sum();
        int delta = (sumA - sumB) / 2;
        Set<Integer> rec = new HashSet<Integer>();
        for (int num : aliceSizes) {
            rec.add(num);
        }
        int[] ans = new int[2];
        for (int y : bobSizes) {
            int x = y + delta;
            if (rec.contains(x)) {
                ans[0] = x;
                ans[1] = y;
                break;
            }
        }
        return ans;
    }
}

解题思路

数学 + 双指针

sumA - sumB 差值其实就是交换需要弥补的差距
定义需要取出来的是 xA 和 xB, 那么它们差值 xA - xB = (sumA - sumB) / 2

思路就是:

    按照从小到大的排序 A 和 B
    双指针,去遍历 A和 B, 考虑三种情况
        xA-xB == (sumA - sumB) / 2 找到答案,返回即可
        xA-xB > (sumA - sumB) / 2 , 则增大 xB
        xA-xB < (sumA - sumB) / 2 , 则增大 xA

class Solution {
public:
    vector<int> fairCandySwap(vector<int>& A, vector<int>& B) {
        int sumA = accumulate(A.begin(), A.end(), 0);
        int sumB = accumulate(B.begin(), B.end(), 0);
        int target = (sumA - sumB) / 2;
        // 默认sort就是从小打大也可以省略 less<int>()
        sort(A.begin(), A.end(), less<int>());
        sort(B.begin(), B.end(), less<int>());

        // 双指针分别指向A和B的开头
        int i = 0;
        int j = 0;
        int nA = A.size();
        int nB = B.size();
        while (i < nA && j < nB)
        {
            int curr = A[i] - B[j];
            if (curr == target)
            {
                return {A[i], B[j]};
            }
            else if (curr > target)
            {
                ++j;
            }
            else
            {
                ++i;
            }
        }

        // 找不到则返回空
        return vector<int>();
    }
};

class Solution {
    public int[] fairCandySwap(int[] aliceSizes, int[] bobSizes) {
        int sum1=0,sum2=0;
        for (int i = 0; i <aliceSizes.length ; i++) {
            sum1+=aliceSizes[i];
        }
        for (int i = 0; i <bobSizes.length ; i++) {
            sum2+=bobSizes[i];
        }
        if(sum1<sum2){
            int n=(sum2-sum1)/2;
            for (int i = 0; i <bobSizes.length ; i++) {
                for (int j = 0; j <aliceSizes.length ; j++) {
                    if(bobSizes[i]-aliceSizes[j]==n){
                        return new int[]{aliceSizes[j],bobSizes[i]};
                    }
                }
            }
        }else {
            int n=(sum1-sum2)/2;
            for (int i = 0; i < aliceSizes.length; i++) {
                for (int j = 0; j < bobSizes.length; j++) {
                    if(aliceSizes[i]-bobSizes[j]==n){
                        return new int[]{aliceSizes[i],bobSizes[j]};
                    }
                }
            }
        }
        return new int[]{};
    }
}

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

毕业_设计

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值