当前位置:   article > 正文

【Py/Java/C++三种语言OD2023C卷真题】20天拿下华为OD笔试之【哈希集合】2023C-CPU算力分配【欧弟算法】全网注释最详细分类最全的华为OD真题题解_python现有俩组服务器a和b,每组有多个算力不同的cpu

python现有俩组服务器a和b,每组有多个算力不同的cpu

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
  • 1
  • 2
  • 3
  • 4

输出描述

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

补充说明

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

示例一

输入

2 2
1 1
2 2
  • 1
  • 2
  • 3

输出

1 2
  • 1

示例二

输入

3 4
1 2 3
1 2 3 4
  • 1
  • 2
  • 3

输出

1 3
  • 1

说明

有两种可能的选择,选择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
  • 1

sum_total一定是一个偶数。

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

即如果交换后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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

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);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42

时空复杂度

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

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


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

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

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

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

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

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

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

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

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/389012
推荐阅读
相关标签
  

闽ICP备14008679号