20天拿下华为OD笔试之【哈希表】2025C-符合要求的结对方式【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-符合要求的结对方式
题目描述与示例
题目描述
用一个数组A代表程序员的工作能力,公司想通过结对编程的方式提高员工的能力,假设结对后的能力为两个员工的能力之和,求一共有多少种结对方式使结对后能力为N。
输入描述
第一行为员工的总人数,取值范围[1,1000]
第二行为数组A的元素,每个元素的取值范围[1,1000]
第三行为N的值,取值范围[1,1000]
输出描述
满足结对后能力为N的结对方式总数。
示例
输入
5
1 2 2 2 3
4
输出
4
说明
满足要求的结对方式为:A[0]和A[4],A[1]和A[2],A[1]和A[3],A[2]和A[3]。
解题思路
本题类似于求配对组数版本的LC1. 两数之和。
容易想到,我们可以使用哈希表计数器Counter()来储存所有数字以及它们出现的频次。
假设存在于A中的两个数字存在num1 + num2 = N成立,我们分情况讨论。若
num1 != num2,它们出现的频率分别是cnt[num1]和cnt[num2],根据乘法原理,它们一共能够构成cnt[num1]*cnt[num2]组不同的组合。num1 = num2 = num,则构成的组数相当于在cnt[num] = m个num中挑选出2个num进行组合,即可以构成 C m 2 = m ( m − 1 ) 2 C_m^2 = \frac{m(m-1)}{2} Cm2=2m(m−1)组不同的组合
再根据加法原理将所有组合数加起来即可。
在代码实现上,如果我们遍历cnt中的所有key,当num1 != num2时会导致重复计算。
所以我们可以额外加一个判断,只考虑所有小于等于N / 2的数字即可。
代码
Python
# 欢迎来到「欧弟算法 - 华为OD全攻略」,收录华为OD题库、面试指南、八股文与学员案例!
# 地址:https://www.odalgo.com
# 华为OD机试刷题网站:https://www.algomooc.com
# 添加微信 278166530 获取华为 OD 笔试真题题库和视频
# 题目:【哈希表】2025C-符合要求的结对方式
# 分值:100
# 作者:许老师-闭着眼睛学数理化
# 算法:哈希表
# 代码看不懂的地方,请直接在群上提问
from collections import Counter
# 员工总人数
m = int(input())
# 输入员工能力值
nums = list(map(int, input().split()))
# 输入结队目标值
N = int(input())
# 统计每个能力值出现的次数
cnt = Counter(nums)
# 统计符合要求的结对方式数量,初始化为0
ans = 0
# 遍历所有能力值
for k in cnt:
# 仅考虑小于等于N / 2的能力值k
# 若k小于N/2,则k和N-k可以组成一对
if k < N / 2:
# 共增加cnt[k] * cnt[N-k]组
ans += cnt[k] * cnt[N-k]
# 若k等于N/2,则k只能和自身组成一对
elif k == N / 2:
# 共增加cnt[k] * (cnt[k] - 1) // 2组
ans += cnt[k] * (cnt[k] - 1) // 2
print(ans)
Java
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 员工总人数
int m = sc.nextInt();
// 员工能力值
int[] nums = new int[m];
for (int i = 0; i < m; i++) nums[i] = sc.nextInt();
// 结队目标值
int N = sc.nextInt();
// 统计每个能力值出现次数
Map<Integer, Integer> cnt = new HashMap<>();
for (int x : nums) cnt.put(x, cnt.getOrDefault(x, 0) + 1);
long ans = 0L;
for (int k : cnt.keySet()) {
int t = N - k;
if (k < t) { // 只从较小的 k 这一侧计数,避免重复
long c1 = cnt.get(k);
long c2 = cnt.getOrDefault(t, 0);
ans += c1 * c2;
} else if (k == t) { // 组内两两配对
long c = cnt.get(k);
ans += c * (c - 1) / 2;
}
// k > t 的情况跳过(已在 t 那一侧统计过)
}
System.out.println(ans);
sc.close();
}
}
C++
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
// 员工总人数
int m;
if (!(cin >> m)) return 0;
// 员工能力值
vector<int> nums(m);
for (int i = 0; i < m; ++i) cin >> nums[i];
// 结队目标值
long long N;
cin >> N;
// 统计每个能力值出现次数
unordered_map<long long, long long> cnt;
cnt.reserve(m * 2);
for (int x : nums) ++cnt[x];
long long ans = 0;
for (const auto& kv : cnt) {
long long k = kv.first;
long long c1 = kv.second;
long long t = N - k;
if (k < t) {
auto it = cnt.find(t);
if (it != cnt.end()) {
ans += c1 * it->second;
}
} else if (k == t) {
ans += c1 * (c1 - 1) / 2;
}
// k > t 跳过,避免重复
}
cout << ans << "\n";
return 0;
}
C
#include <stdio.h>
#include <stdlib.h>
/* 快速比较函数:用于 qsort 将数组按升序排序 */
static int cmp_ll(const void *a, const void *b) {
long long x = *(const long long*)a;
long long y = *(const long long*)b;
return (x < y) ? -1 : (x > y);
}
int main(void) {
// 员工总人数
int m;
if (scanf("%d", &m) != 1) return 0;
// 读取员工能力值(用 long long 存,兼容大值/负数)
long long *arr = (long long*)malloc(sizeof(long long) * (size_t)m);
if (!arr) return 1;
for (int i = 0; i < m; ++i) {
long long v;
scanf("%lld", &v);
arr[i] = v;
}
// 结队目标值 N
long long N;
scanf("%lld", &N);
// 排序后用双指针统计所有 (i<j) 且 arr[i]+arr[j]==N 的配对数
qsort(arr, (size_t)m, sizeof(long long), cmp_ll);
long long ans = 0;
int l = 0, r = m - 1;
while (l < r) {
long long sum = arr[l] + arr[r];
if (sum < N) {
++l;
} else if (sum > N) {
--r;
} else {
// sum == N
if (arr[l] == arr[r]) {
// 区间内元素都相等:从 l 到 r 的任取两两配对
long long k = (long long)(r - l + 1);
ans += k * (k - 1) / 2;
break; // 全部处理完毕
} else {
// 统计左侧相同值的个数 c1,右侧相同值的个数 c2
long long leftVal = arr[l], rightVal = arr[r];
long long c1 = 0, c2 = 0;
while (l <= r && arr[l] == leftVal) { ++c1; ++l; }
while (r >= l && arr[r] == rightVal) { ++c2; --r; }
ans += c1 * c2; // 左组与右组的任意组合
}
}
}
printf("%lld\n", ans);
free(arr);
return 0;
}
Node JavaScript
// 使用 Node.js 的 Map 来统计频率
const readline = require("readline");
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
let input = [];
rl.on("line", line => {
input.push(line.trim());
});
rl.on("close", () => {
// 员工总人数
let m = parseInt(input[0]);
// 员工能力值
let nums = input[1].split(" ").map(Number);
// 结队目标值
let N = parseInt(input[2]);
// 统计每个能力值出现次数
let cnt = new Map();
for (let x of nums) {
cnt.set(x, (cnt.get(x) || 0) + 1);
}
let ans = 0n; // 使用 BigInt 避免大数溢出
for (let [k, c1] of cnt.entries()) {
let t = N - k;
if (k < t) {
let c2 = BigInt(cnt.get(t) || 0);
ans += BigInt(c1) * c2;
} else if (k === t) {
let c = BigInt(c1);
ans += c * (c - 1n) / 2n;
}
// k > t 的情况跳过
}
console.log(ans.toString());
});
Go
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
in := bufio.NewReader(os.Stdin)
// 员工总人数
line, _ := in.ReadString('\n')
m, _ := strconv.Atoi(strings.TrimSpace(line))
// 员工能力值
line, _ = in.ReadString('\n')
parts := strings.Fields(line)
nums := make([]int, m)
for i := 0; i < m; i++ {
nums[i], _ = strconv.Atoi(parts[i])
}
// 结队目标值
line, _ = in.ReadString('\n')
N, _ := strconv.Atoi(strings.TrimSpace(line))
// 统计每个能力值出现次数
cnt := make(map[int]int)
for _, x := range nums {
cnt[x]++
}
var ans int64 = 0
for k, c1 := range cnt {
t := N - k
if k < t {
if c2, ok := cnt[t]; ok {
ans += int64(c1) * int64(c2)
}
} else if k == t {
c := int64(c1)
ans += c * (c - 1) / 2
}
// k > t 跳过
}
fmt.Println(ans)
}
时空复杂度
时间复杂度:O(m)。构建哈希表和遍历哈希表所需的时间复杂度。
空间复杂度:O(m)。哈希表所占空间。
华为OD算法/大厂面试高频题算法练习冲刺训练
-
华子OD算法/大厂面试高频题算法冲刺训练目前开始常态化报名!目前已服务1000+同学成功上岸!
-
课程讲师为全网200w+粉丝编程博主@吴师兄学算法 以及小红书头部编程博主@闭着眼睛学数理化
-
90+天陪伴式学习,100+直播课时,300+动画图解视频,500+LeetCode经典题,500+华为OD真题/大厂真题,还有简历修改、模拟面试、陪伴小群、资深HR对接将为你解锁
-
可上全网独家的欧弟OJ系统练习华子OD、大厂真题
-
可查看链接OD真题汇总(持续更新)
-
绿色聊天软件戳
od1441或了解更多
更多推荐



所有评论(0)