前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【刷穿 LeetCode】888. 公平的糖果棒交换(简单)

【刷穿 LeetCode】888. 公平的糖果棒交换(简单)

作者头像
宫水三叶的刷题日记
发布2021-02-20 09:44:09
4940
发布2021-02-20 09:44:09
举报
文章被收录于专栏:宫水三叶的刷题日记

题目描述

爱丽丝和鲍勃有不同大小的糖果棒:A[i] 是爱丽丝拥有的第 i 根糖果棒的大小,B[j] 是鲍勃拥有的第 j 根糖果棒的大小。

因为他们是朋友,所以他们想交换一根糖果棒,这样交换后,他们都有相同的糖果总量。(一个人拥有的糖果总量是他们拥有的糖果棒大小的总和。)

返回一个整数数组 ans,其中 ans[0] 是爱丽丝必须交换的糖果棒的大小,ans[1] 是 Bob 必须交换的糖果棒的大小。

如果有多个答案,你可以返回其中任何一个。保证答案存在。

示例 1:

代码语言:javascript
复制
输入:A = [1,1], B = [2,2]
输出:[1,2]

示例 2:

代码语言:javascript
复制
输入:A = [1,2], B = [2,3]
输出:[1,2]

示例 3:

代码语言:javascript
复制
输入:A = [2], B = [1,3]
输出:[2,3]

示例 4:

代码语言:javascript
复制
输入: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
  • 保证爱丽丝与鲍勃的糖果总量不同。
  • 答案肯定存在。

朴素解法

我们最终目的是让两个数组总和一样。

我们可以先分别求得两者数组总和为 aSumbSum,可得两者数组总和 total = aSum + bSum,也可得数组目标总和为 target = total / 2,最终可得两者的具体差值分别为 target - aSumtarget - bSum,两者互为互为相反数,记绝对值为 diff

之后对 a 数组进行遍历。假定 aSum < bSum,对于 a[i] 而言,如果 a[i] 能构成答案,那么必然 b 数组中必然存在 a[i] + diff 的值,使得两者交换后,数组总和均为 target

因此对于每个 a[i] 而言,我们需要到 b 数组中找是否存在 a[i] + diff。如果存在输出答案,没有的话检查下一个 a[i]

代码:

代码语言:javascript
复制
class Solution {
    public int[] fairCandySwap(int[] a, int[] b) {
        int aSum = 0, bSum = 0;
        for (int i : a) aSum += i;  
        for (int i : b) bSum += i;  
        int total = aSum + bSum, target = total / 2;
        int diff = target - aSum;
        int[] ans = new int[2];
        for (int i : a) {
            if (find(b, i + diff)) {
                ans[0] = i;
                ans[1] = i + diff;
            }
        }
        return ans;
    }
    boolean find(int[] nums, int target) {
        for (int i : nums) {
            if (i == target) return true;
        }
        return false;
    }
}
  • 时间复杂度:计算总和复杂度为
O(n)

,找到最终解复杂度为

O(n^2)

。整体复杂度为

O(n^2)

  • 空间复杂度:
O(1)

查找优化解法

上述解法主要的时间消耗在 b 数组中查找 a[i] + diff 是否存在。

我们知道 map/set/数组 都可以实现

O(1)

查找,由于这里明确给出了两个数组中出现的数的范围,因此我使用数组进行计数。

同时优化了一下变量的使用,使用一个变量 diff 来计算最终的差异值。

这种优化,是典型的空间换时间做法:

代码语言:javascript
复制
class Solution {
    public int[] fairCandySwap(int[] a, int[] b) {
        // 先求得 a 的总和
        int diff = 0;
        for (int i : a) diff += i;  

        // 使用 cnt 统计 b 中的数的出现次数,同时计算 a 总和与 b 总和的差值
        int[] cnt = new int[100009];
        for (int i : b) {
            diff -= i;
            cnt[i]++;
        }

        // 计算出 a 中具体的替换差异量是多少
        diff /= -2;
        int[] ans = new int[2];
        for (int i : a) {
            int target = i + diff;
            // 如果目标替换量在合法范围,并且存在于 b 数组中。说明找到解了
            if (target >= 1 && target <= 100000 && cnt[target] > 0) {
                ans[0] = i;
                ans[1] = target;
                break;
            }
        }
        return ans;
    }
}
  • 时间复杂度:计算总和复杂度为
O(n)

,找到最终解复杂度为

O(n)

。整体复杂度为

O(n)

  • 空间复杂度:使用 cnt 数组进行计数。复杂度为
O(n)

最后

这是我们「刷穿 LeetCode」系列文章的第 No.* 篇,系列开始于 2021/01/01,截止于起始日 LeetCode 上共有 1916 道题目,部分是有锁题,我们将先将所有不带锁的题目刷完。

在这个系列文章里面,除了讲解解题思路以外,还会尽可能给出最为简洁的代码。如果涉及通解还会相应的代码模板。

由于 LeetCode 的题目随着周赛 & 双周赛不断增加,为了方便我们统计进度,我们将按照系列起始时的总题数作为分母,完成的题目作为分子,进行进度计算。当前进度为 */1916

为了方便各位同学能够电脑上进行调试和提交代码,我在 Github 建立了相关的仓库:https://github.com/SharingSource/LogicStack-LeetCode。

在仓库地址里,你可以看到系列文章的题解链接、系列文章的相应代码、LeetCode 原题链接和一些其他的优选题解。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-02-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 宫水三叶的刷题日记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 题目描述
  • 朴素解法
  • 查找优化解法
  • 最后
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档