20天拿下华为OD笔试之【哈希集合】2025C-最大N个数与最小N个数的和【Py/Java/C++/C/JS/Go六种语言OD独家2025C卷真题】【欧弟算法】全网注释最详细分类最全的华子OD真题题解
·
可上 欧弟OJ系统 练习华子OD、大厂真题
绿色聊天软件戳od1441了解算法冲刺训练(备注【CSDN】否则不通过)
文章目录
相关推荐阅读
- 【华为OD机考】2025C+2025B+2024E+D卷真题【完全原创题解 | 详细考点分类 | 不断更新题目】
- 【华为OD笔试】2025C+2025B+2024E+D卷真题机考套题汇总【真实反馈,不断更新,限时免费】
- 【华为OD笔试】2024E+D卷命题规律解读【分析500+场OD笔试考点总结】
- 【华为OD流程】性格测试选项+注意事项】
题目练习网址:【哈希集合】2025C-最大N个数与最小N个数的和
题目描述与示例
题目描述
给定一个数组,编写一个函数来计算它的最大N个数与最小N个数的和。你需要对数组进行去重。
输入描述
第一行输入M, M标识数组大小
第二行输入M个数,标识数组内容
第三行输入N,N表达需要计算的最大、最小N个数
输出描述
输出最大N个数与最小N个数的和。
补充说明
数组中数字范围[0,1000]
最大N个数与最小N个数不能有重叠,如有重叠返回-1
示例
输入
5
95 88 83 64 100
2
输出
342
解题思路
直白、简单的题目。主要考察以下几个知识点
- 哈希集合去重
- 去重后的结果再次排序得到新列表
lst_new lst_new的长度必须大于2*N- 计算最大的
N个数和最小的N个数的和
代码
Python
# 欢迎来到「欧弟算法 - 华为OD全攻略」,收录华为OD题库、面试指南、八股文与学员案例!
# 地址:https://www.odalgo.com
# 华为OD机试刷题网站:https://www.algomooc.com
# 添加微信 278166530 获取华为 OD 笔试真题题库和视频
# 题目:2023C/2024D/2025C-最大N个数与最小N个数的和
# 分值:100
# 作者:闭着眼睛学数理化
# 算法:哈希集合,排序
# 代码看不懂的地方,请直接在群上提问
m = int(input())
lst = list(map(int, input().split()))
n = int(input())
# 使用set进行去重,然后对去重后的结果进行排序
lst_new = sorted(set(lst))
# 如果lst_new的长度小于2*n
# 说明最大N个数和最小N个数出现了重叠,输出-1
if len(lst_new) < 2*n:
print(-1)
# 否则,使用切片和sum(),计算最大N个数和最小N个数的和
else:
print(sum(lst_new[:n]) + sum(lst_new[len(lst_new)-n:]))
Java
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int m = scanner.nextInt();
List<Integer> lst = new ArrayList<>();
for (int i = 0; i < m; ++i) {
lst.add(scanner.nextInt());
}
int n = scanner.nextInt();
// 使用 Set 进行去重,并对其进行排序
Set<Integer> uniqueSet = new TreeSet<>(lst);
List<Integer> lstNew = new ArrayList<>(uniqueSet);
if (lstNew.size() < 2 * n) {
System.out.println(-1);
} else {
long sum = 0;
for (int i = 0; i < n; ++i) {
sum += lstNew.get(i) + lstNew.get(lstNew.size() - 1 - i);
}
System.out.println(sum);
}
}
}
C++
#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
using namespace std;
int main() {
int m, n;
cin >> m;
vector<int> lst(m);
for (int i = 0; i < m; ++i) {
cin >> lst[i];
}
cin >> n;
// 使用 set 进行去重,并对其进行排序
set<int> uniqueSet(lst.begin(), lst.end());
vector<int> lstNew(uniqueSet.begin(), uniqueSet.end());
sort(lstNew.begin(), lstNew.end());
if (lstNew.size() < 2 * n) {
cout << -1 << endl;
} else {
long long sum = 0;
for (int i = 0; i < n; ++i) {
sum += lstNew[i] + lstNew[lstNew.size() - 1 - i];
}
cout << sum << endl;
}
return 0;
}
C
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
/*
说明(关于 C 语言中替代 C++ set 的做法):
- C 语言没有现成的 set 容器,为实现“使用 set 进行去重,并对其进行排序”的效果,
我们先对原数组进行升序排序(qsort),再线性扫描压缩相邻重复元素,得到去重后的有序数组。
*/
/* qsort 比较函数:升序排序 */
static int cmp_int_asc(const void *a, const void *b) {
int ia = *(const int *)a;
int ib = *(const int *)b;
if (ia < ib) return -1;
if (ia > ib) return 1;
return 0;
}
int main(void) {
int m, n;
/* 读入 m */
if (scanf("%d", &m) != 1) {
return 0; /* 输入异常时直接结束 */
}
/* 读入 m 个整数 */
int *lst = (int *)malloc(sizeof(int) * (m > 0 ? m : 1));
if (!lst) {
return 0; /* 内存分配失败,直接结束 */
}
for (int i = 0; i < m; ++i) {
scanf("%d", &lst[i]);
}
/* 读入 n */
scanf("%d", &n);
/*
使用 set 进行去重,并对其进行排序
—— 在 C 中的等价实现:
1) 先对 lst 升序排序;
2) 再将相邻相同的元素压缩掉,得到去重后的有序数组 lstNew。
*/
qsort(lst, m, sizeof(int), cmp_int_asc);
// 统计去重后的大小(先遍历计算 unique 的个数)
int unique_cnt = 0;
if (m > 0) {
unique_cnt = 1;
for (int i = 1; i < m; ++i) {
if (lst[i] != lst[i - 1]) {
++unique_cnt;
}
}
}
// 分配去重后的数组并填充
int *lstNew = (int *)malloc(sizeof(int) * (unique_cnt > 0 ? unique_cnt : 1));
if (!lstNew) {
free(lst);
return 0;
}
int idx = 0;
if (m > 0) {
lstNew[idx++] = lst[0];
for (int i = 1; i < m; ++i) {
if (lst[i] != lst[i - 1]) {
lstNew[idx++] = lst[i];
}
}
}
// 此时 lstNew 已经是升序且元素唯一
// 判断是否满足 2*n 的配对需求
if (unique_cnt < 2 * n) {
printf("-1\n");
} else {
long long sum = 0; // 使用 long long 存储求和,避免溢出
for (int i = 0; i < n; ++i) {
sum += (long long)lstNew[i] + (long long)lstNew[unique_cnt - 1 - i];
}
printf("%lld\n", sum);
}
free(lstNew);
free(lst);
return 0;
}
Node JavaScript
"use strict";
/**
* 读取标准输入并解析为字符串数组
*/
const fs = require("fs");
const input = fs.readFileSync(0, "utf8").trim().split(/\s+/);
// 指针用于按顺序取数
let idx = 0;
// 读入 m
const m = Number(input[idx++]);
const uniq = new Set();
for (let i = 0; i < m; ++i) {
const val = BigInt(input[idx++]);
uniq.add(val); // 去重
}
// 读入 n
const n = Number(input[idx++]);
// 将去重结果转为数组并排序(升序)
const lstNew = Array.from(uniq);
lstNew.sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
// 若去重后的元素个数小于 2*n,则无法两两配对,输出 -1
if (lstNew.length < 2 * n) {
console.log(-1);
} else {
// 从两端向中间配对求和:最小配最大的、次小配次大的
let sum = 0n;
for (let i = 0; i < n; ++i) {
sum += lstNew[i] + lstNew[lstNew.length - 1 - i];
}
// 输出时转为字符串,避免 BigInt 与默认输出不兼容
console.log(sum.toString());
}
Go
package main
import (
"bufio"
"fmt"
"os"
"sort"
)
func main() {
in := bufio.NewReader(os.Stdin)
var m int
if _, err := fmt.Fscan(in, &m); err != nil {
return
}
// 使用 map 充当 Set 进行去重(键为元素值,值为是否出现)
unique := make(map[int64]bool)
for i := 0; i < m; i++ {
var x int64
fmt.Fscan(in, &x)
unique[x] = true
}
var n int
fmt.Fscan(in, &n)
// 将去重后的键转为切片并进行升序排序
lstNew := make([]int64, 0, len(unique))
for k := range unique {
lstNew = append(lstNew, k)
}
sort.Slice(lstNew, func(i, j int) bool { return lstNew[i] < lstNew[j] })
// 判断是否满足 2*n 个可配对元素
if len(lstNew) < 2*n {
fmt.Println(-1)
return
}
// 从两端向中间配对求和
var sum int64 = 0
for i := 0; i < n; i++ {
sum += lstNew[i] + lstNew[len(lstNew)-1-i]
}
fmt.Println(sum)
}
时空复杂度
时间复杂度:O(MlogM)。排序所需时间复杂度
空间复杂度:O(M)。
华为OD算法/大厂面试高频题算法练习冲刺训练
-
华子OD算法/大厂面试高频题算法冲刺训练目前开始常态化报名!目前已服务1000+同学成功上岸!
-
课程讲师为全网200w+粉丝编程博主@吴师兄学算法 以及小红书头部编程博主@闭着眼睛学数理化
-
90+天陪伴式学习,100+直播课时,300+动画图解视频,500+LeetCode经典题,500+华为OD真题/大厂真题,还有简历修改、模拟面试、陪伴小群、资深HR对接将为你解锁
-
可上全网独家的欧弟OJ系统练习华子OD、大厂真题
-
可查看链接OD真题汇总(持续更新)
-
绿色聊天软件戳
od1441或了解更多
更多推荐



所有评论(0)