【Py/Java/C++三种语言OD2023C卷真题】20天拿下华为OD笔试之【哈希集合】2023C-CPU算力分配【欧弟算法】全网注释最详细分类最全的华为OD真题题解

有LeetCode算法/华为OD考试扣扣交流群可加 948025485
可上全网独家的 欧弟OJ系统 练习华子OD、大厂真题
绿色聊天软件戳 od1336了解算法冲刺训练

题目描述与示例

题目描述

现有两组服务器AB,每组有多个算力不同的CPU,其中AiA组第i个CPU的运算能力,BiB组第i个CPU的运算能力。一组服务器的总算力是各CPU的算力之和。

为了让两组服务器的算力相等,允许从每组各选出一个CPU进行一次交换,求两组服务器中,用于交换的CPU的算力,并且要求从A组服务器中选出的CPU,算力尽可能小。

输入描述

第一行输入为L1L2,以空格分隔,L1表示A组服务器中的CPU数量,L2表示B组服务器中的CPU数量

第二行输入为A组服务器中各个CPU的算力值,以空格分隔。

第三行输入为B组服务器中各个CPU的算力值,以空格分隔,

1 <= L1 <= 10000
1 <= L2 <= 10000
1 <= A[i] <= 100000
1 <= B[i] <= 100000

输出描述

对于每组测试数据,输出两个整数,以空格分隔,依次表示A组选出的CPU算力、B组选出的CPU算力,要求从A组选出的CPU的算力尽可能小。

补充说明

保证两组服务器的初始总算力不同,答案肯定存在。

示例一

输入

2 2
1 1
2 2

输出

1 2

示例二

输入

3 4
1 2 3
1 2 3 4

输出

1 3

说明

有两种可能的选择,选择A组中的1B组中的3进行交换,或者选择A组中的2B组中的4进行交换,但由于要求A组选择的算力要尽可能地小,所以选择前者。

解题思路

注意有两个非常重要的条件:

  1. 允许从每组各选出一个CPU进行一次交换
  2. 保证两组服务器的初始总算力不同,答案肯定存在

第一个条件指出,只能在A组和B组中各挑选出1个数据,不用考虑多组交换的情况

第二个条件指出,无需考虑不合规则的情况,必然能够找到一个A[i]和一个B[j],交换后使得各自的和相等。

假设原A组的和为sumA,原B组的和为sumB,所有CPU的算力总和为sum_total,取出的两个用于交换的元素分别为A[i]B[j]

交换后,如果A组的和为sumA_newB组的和为sumB_new,那么一定存在以下式子成立

sumA_new = sumB_new = sum_total // 2

sum_total一定是一个偶数。

A`组少了一个`A[i]`多了一个`B[j]`,故变化量为`sumA_new - sumA = B[j] - A[i]

即如果交换后A组和B组的算力总和相等,存在式子B[j] = sumA - sumA_new + A[i]成立。

因此,我们只需要遍历A组中所有的元素A[i],然后计算对应的sumA_new - sumA + A[i],如果该值位于B组中,说明B组中可以找到对应的B[j]

这个步骤涉及到快速查找,因此很容易想到应该构建哈希集合setB = set(B)

从示例二可以得知,可以交换的组数不是唯一的。由于题目还要求从A组服务器中选出的CPU,算力尽可能小,因此仅需把所有符合条件的A[i]取最小值即可。

另外,由于A组中可能出现重复元素,重复元素的计算对于本问题而言是无意义的,因此也可以构建setA = set(A),遍历A组元素时直接遍历setA而非A即可。

代码

Python

# 题目:【哈希集合】2023C-CPU算力分配
# 分值:100
# 作者:闭着眼睛学数理化
# 算法:哈希集合,数学
# 代码看不懂的地方,请直接在群上提问


# 输入A组的长度和B组的长度
nA, nB = map(int, input().split())
# 输入A组的情况
A = list(map(int, input().split()))
# 输入B组的情况
B = list(map(int, input().split()))

# 原A组的总和
sumA = sum(A)
# 原B组的总和
sumB = sum(B)
# 交换后A组的和,为所有元素总和的一半
sumA_new = (sumA + sumB) // 2

# 分别获得A组和B组对应的哈希集合
# setA的作用是去重,setB的作用是快速查找
setA = set(A)
setB = set(B)

# 找到所有满足sumA_new - sumA + Ai位于setB中的Ai的最小值,即为A组中所选的算力ansA
ansA = min(Ai for Ai in setA if (sumA_new - sumA + Ai) in setB)
# 对应地可以计算出ansB
ansB = sumA_new - sumA + ansA

# 输出答案
print(ansA, ansB)

Java

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int nA = scanner.nextInt();
        int nB = scanner.nextInt();
        int[] A = new int[nA];
        int[] B = new int[nB];
        for (int i = 0; i < nA; i++) {
            A[i] = scanner.nextInt();
        }
        for (int i = 0; i < nB; i++) {
            B[i] = scanner.nextInt();
        }

        int sumA = 0, sumB = 0;
        for (int num : A) {
            sumA += num;
        }
        for (int num : B) {
            sumB += num;
        }
        int sumANew = (sumA + sumB) / 2;

        Set<Integer> setB = new HashSet<>();
        for (int num : B) {
            setB.add(num);
        }

        int ansA = Integer.MAX_VALUE;
        for (int num : A) {
            if (setB.contains(sumANew - sumA + num)) {
                ansA = Math.min(ansA, num);
            }
        }
        int ansB = sumANew - sumA + ansA;
        System.out.println(ansA + " " + ansB);
    }
}

C++

#include <iostream>
#include <vector>
#include <unordered_set>
#include <algorithm>
#include <climits>

using namespace std;

int main() {
    int nA, nB;
    cin >> nA >> nB;
    vector<int> A(nA), B(nB);
    for (int i = 0; i < nA; i++) {
        cin >> A[i];
    }
    for (int i = 0; i < nB; i++) {
        cin >> B[i];
    }

    int sumA = 0, sumB = 0;
    for (int num : A) {
        sumA += num;
    }
    for (int num : B) {
        sumB += num;
    }
    int sumANew = (sumA + sumB) / 2;

    unordered_set<int> setB(B.begin(), B.end());

    int ansA = INT_MAX;
    for (int num : A) {
        if (setB.count(sumANew - sumA + num)) {
            ansA = min(ansA, num);
            
        }
    }
    int ansB = sumANew - sumA + ansA;
    cout << ansA << " " << ansB << endl;

    return 0;
}

时空复杂度

时间复杂度:O(N+M)。构建两个哈希集合所需的时间复杂度

空间复杂度:O(N+M)。两个哈希集合所占的空间。


华为OD算法/大厂面试高频题算法练习冲刺训练

  • 华为OD算法/大厂面试高频题算法冲刺训练目前开始常态化报名!目前已服务300+同学成功上岸!

  • 课程讲师为全网50w+粉丝编程博主@吴师兄学算法 以及小红书头部编程博主@闭着眼睛学数理化

  • 每期人数维持在20人内,保证能够最大限度地满足到每一个同学的需求,达到和1v1同样的学习效果!

  • 60+天陪伴式学习,40+直播课时,300+动画图解视频,300+LeetCode经典题,200+华为OD真题/大厂真题,还有简历修改、模拟面试、专属HR对接将为你解锁

  • 可上全网独家的欧弟OJ系统练习华子OD、大厂真题

  • 可查看链接 大厂真题汇总 & OD真题汇总(持续更新)

  • 绿色聊天软件戳 od1336了解更多

  • 11
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值