华为笔试 华为笔试题 20260304
笔试时间:2026年03月04日
往年笔试合集:
华为笔试题解
笔试时间:2026年3月4日
第一题:网络流量分析
难度:中等
涉及知识点: KMeans聚类算法实现、欧式距离计算、聚类中心更新、数值精度处理
题目描述
网络流量分析是网络安全和性能优化的关键任务。假设你有一个包含网络流量数据的数据,每条数据包包含以下特征:
packet_size(数据包大小,单位:字节)inter_arrival_time(数据包到达间隔时间,单位:毫秒)protocol_type(协议类型,如TCP、UDP、ICMP等,已转换为数值编码)
你的任务是使用KMeans聚类算法对网络流量进行分类,分类后的中心点再经过一个分类头,能识别出可能的流量类型(如正常流量、异常流量、DDoS攻击流量等)。KMeans算法原理为:先将数据划分为K组,随机选取K个对象作为初始的聚类中心,然后计算每个对象与各个聚类中心之间的距离,将每个对象分配给距离它最近的聚类中心,聚类中心以及分配给它们的对象就代表一个聚类。(为保证结果固定,本题初始的聚类中心已给出,不需要随机)
输入描述
- 初始聚类点个数 K
- 初始聚类中心点集合(往下 K 行,一行一个中心点)
- 迭代次数
- 样本个数 M
- 样本数据,每个样本有三个特征(往下 M 行,各种特征数据已归一化处理,各维度权重占比一致)
输出描述
按给定次数迭代后新的聚类中心集合,结果保留两位小数,注意四舍五入。
样例1
输入:
3 50 25 30 60 15 60 25 75 90 3 9 50 25 30 30 50 30 60 15 60 25 75 90 100 5 60 26 15 30 32 67.5 90 80 7.5 60 20 100 90
输出:
35.33 30.00 30.00 80.00 9.17 60.00 25.67 80.83 90.00
说明: 采用欧式距离计算不同数据之间的距离:计算每个特征距离中心点的距离,选择距离最近的点作为当前特征归属的类别;按照划分的类别,重新计算每个类别的中心点,完成一轮迭代(中心点为对应类型所有样本的平均值)。重复上述流程指定次数得到结果。
样例2
输入:
3 50 20 30 60 10 60 180 180 180 3 8 50 20 30 30 50 30 60 10 60 25 75 90 100 5 60 30 60 90 80 10 60 180 180 180
输出:
40.00 35.00 30.00 59.00 32.00 72.00 180.00 180.00 180.00
提示
- 初始聚类中心点个数:≤1000,类型为 int
- 初始聚类中心点集合:每个特征的取值范围为 0~1000,类型为 float
- 迭代次数:≤1000,类型为 int
- 初始特征个数:≤1000,类型为 int
- 初始特征集合:每个特征的取值范围为 0~1000,类型为 int
参考题解
解题思路:
这是一个KMeans聚类算法的模拟实现问题。给定初始聚类中心、样本点和迭代次数,需要模拟KMeans算法的迭代过程,输出迭代后的聚类中心。
- 距离计算: 使用欧几里得距离(欧式距离)计算样本点与聚类中心的距离。优化技巧:计算距离的平方,避免开方运算,因为比较距离大小时,平方距离和实际距离的排序是一致的。
- 分配阶段: 对于每个样本点,计算它与所有聚类中心的距离,找到距离最近的聚类中心,将该样本点分配到对应的聚类中。
- 更新阶段: 对于每个聚类,如果聚类中有样本点,计算所有样本点在三个维度上的平均值作为新的聚类中心;如果聚类中没有样本点,保持原来的聚类中心不变。
- 迭代过程: 重复执行分配阶段和更新阶段,直到达到指定的迭代次数。
算法复杂度: 每次迭代 O(N×K),总复杂度 O(T×N×K),由于 T、N、K 都≤1000,最坏情况下约 10^9 次运算。
Python:
import sys
from decimal import Decimal, ROUND_HALF_UP
def round_half_up(val):
val_str = f"{val:.10f}"
dec = Decimal(val_str).quantize(Decimal('0.00'), rounding=ROUND_HALF_UP)
return f"{dec:.2f}"
k = int(sys.stdin.readline().strip())
centers = []
for _ in range(k):
parts = sys.stdin.readline().strip().split()
centers.append([float(parts[0]), float(parts[1]), float(parts[2])])
iterations = int(sys.stdin.readline().strip())
m = int(sys.stdin.readline().strip())
points = []
for _ in range(m):
parts = sys.stdin.readline().strip().split()
points.append([float(parts[0]), float(parts[1]), float(parts[2])])
for _ in range(iterations):
clusters = [[] for _ in range(k)]
for p in points:
best_c = -1
best_dist = float('inf')
for i, c in enumerate(centers):
dist_sq = sum((p[j] - c[j]) ** 2 for j in range(3))
if dist_sq < best_dist:
best_dist = dist_sq
best_c = i
clusters[best_c].append(p)
new_centers = []
for i in range(k):
if clusters[i]:
new_c = [sum(x[j] for x in clusters[i]) / len(clusters[i]) for j in range(3)]
new_centers.append(new_c)
else:
new_centers.append(centers[i])
centers = new_centers
for c in centers:
print(" ".join(round_half_up(x) for x in c))
C++:
#include <iostream>
#include <vector>
#include <cmath>
#include <climits>
#include <iomanip>
#include <cstdio>
using namespace std;
// 标准四舍五入保留两位小数
string roundHalfUp(double val) {
// 加上一个极小量避免浮点误差导致的截断问题
double rounded = floor(val * 100.0 + 0.5 + 1e-9) / 100.0;
char buf[32];
sprintf(buf, "%.2f", rounded);
return string(buf);
}
int main() {
int k;
cin >> k;
vector<vector<double>> centers(k, vector<double>(3));
for (int i = 0; i < k; i++) {
cin >> centers[i][0] >> centers[i][1] >> centers[i][2];
}
int iterations;
cin >> iterations;
int m;
cin >> m;
vector<vector<double>> points(m, vector<double>(3));
for (int i = 0; i < m; i++) {
cin >> points[i][0] >> points[i][1] >> points[i][2];
}
for (int iter = 0; iter < iterations; iter++) {
vector<vector<vector<double>>> clusters(k);
for (int p = 0; p < m; p++) {
int bestC = -1;
double bestDist = 1e18;
for (int i = 0; i < k; i++) {
double distSq = 0;
for (int j = 0; j < 3; j++) {
double diff = points[p][j] - centers[i][j];
distSq += diff * diff;
}
if (distSq < bestDist) {
bestDist = distSq;
bestC = i;
}
}
clusters[bestC].push_back(points[p]);
}
vector<vector<double>> newCenters(k, vector<double>(3, 0.0));
for (int i = 0; i < k; i++) {
if (!clusters[i].empty()) {
for (int j = 0; j < 3; j++) {
double sum = 0;
for (auto& pt : clusters[i]) {
sum += pt[j];
}
newCenters[i][j] = sum / clusters[i].size();
}
} else {
newCenters[i] = centers[i];
}
}
centers = newCenters;
}
for (int i = 0; i < k; i++) {
for (int j = 0; j < 3; j++) {
if (j > 0) cout << " ";
cout << roundHalfUp(centers[i][j]);
}
cout << endl;
}
return 0;
}
Java:
import java.util.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
public class Main {
static String roundHalfUp(double val) {
BigDecimal bd = new BigDecimal(String.format("%.10f", val));
bd = bd.setScale(2, RoundingMode.HALF_UP);
return bd.toPlainString();
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int k = Integer.parseInt(sc.nextLine().trim());
double[][] centers = new double[k][3];
for (int i = 0; i < k; i++) {
String[] parts = sc.nextLine().trim().split("\\s+");
centers[i][0] = Double.parseDouble(parts[0]);
centers[i][1] = Double.parseDouble(parts[1]);
centers[i][2] = Double.parseDouble(parts[2]);
}
int iterations = Integer.parseInt(sc.nextLine().trim());
int m = Integer.parseInt(sc.nextLine().trim());
double[][] points = new double[m][3];
for (int i = 0; i < m; i++) {
String[] parts = sc.nextLine().trim().split("\\s+");
points[i][0] = Double.parseDouble(parts[0]);
points[i][1] = Double.parseDouble(parts[1]);
points[i][2] = Double.parseDouble(parts[2]);
}
for (int iter = 0; iter < iterations; iter++) {
List<List<double[]>> clusters = new ArrayList<>();
for (int i = 0; i < k; i++) {
clusters.add(new ArrayList<>());
}
for (int p = 0; p < m; p++) {
int bestC = -1;
double bestDist = Double.MAX_VALUE;
for (int i = 0; i < k; i++) {
double distSq = 0;
for (int j = 0; j < 3; j++) {
double diff = points[p][j] - centers[i][j];
distSq += diff * diff;
}
if (distSq < bestDist) {
bestDist = distSq;
bestC = i;
}
}
clusters.get(bestC).add(points[p]);
}
double[][] newCenters = new double[k][3];
for (int i = 0; i < k; i++) {
if (!clusters.get(i).isEmpty()) {
for (int j = 0; j < 3; j++) {
double sum = 0;
for (double[] pt : clusters.get(i)) {
sum += pt[j];
}
newCenters[i][j] = sum / clusters.get(i).size();
}
} else {
newCenters[i] = centers[i].clone();
}
}
centers = newCenters;
}
StringBuilder sb = new StringBuilder();
for (int i = 0; i < k; i++) {
sb.append(roundHalfUp(centers[i][0]));
sb.append(" ");
sb.append(roundHalfUp(centers[i][1]));
sb.append(" ");
sb.append(roundHalfUp(centers[i][2]));
sb.append("\n");
}
System.out.print(sb);
}
}
第二题:动态区间的多项式岭回归
难度:较高
涉及知识点: 时间序列分析、岭回归建模、动态区间确定、矩阵运算、二阶多项式拟合
题目描述
某大型互联网公司的网管中心,记录了其核心服务在连续 N 天内的出口总流量(单位 GB,取值范围通常在 100 到 500.00 之间),
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
2025打怪升级记录,大厂笔试合集 C++, Java, Python等多种语言做法集合指南
