华为笔试 华为春招实习 华为第一场实习笔试真题解析 0408
笔试时间:2026年4月8日
往年笔试合集:
第一题:路由器资源用量预测(150分)
题目
路由器的某资源利用率与多个运行特征强相关:协议连接数(单位:个)、转发数据包速率(单位:Mpps)、内存占用率(单位:%)。
为了精准预测不同负载下的路由器资源利用率,保障网络稳定运行,请实现批量梯度下降法(BGD)来训练资源预测线性回归模型的参数。
资源预测模型:
y = w0 + w1·x1 + w2·x2 + w3·x3
(w0 为偏置项,x1、x2、x3 分别为特征,w1、w2、w3 为特征权重)
损失函数: 均方误差(MSE)
L = (1 / (2m)) · Σ (y_hat_i - y_i)² (m 为样本数)
梯度更新规则:
wj = wj - α · (1/m) · Σ (y_hat_i - y_i) · x_ij
(偏置项 w0 对应 x_i0 = 1,α 为学习率)
迭代规则: 初始权重(含偏置)全为 0,迭代固定 N 次后停止,无需判断收敛。
为了提高收敛速度,采用特征归一化进行训练,并在训练完成后进行权重还原:
- 特征归一化: 对每个特征维度 j(j = 1, 2, 3):其中 x_min_j 为该特征在所有样本中的最小值,x_max_j 为该特征在所有样本中的最大值。若 x_max_j = x_min_j(即特征无波动),则归一化后的值为 0。
- 特征权重还原:w_j 为迭代后的权重。若 x_max_j = x_min_j,则 w_j' 取 0。
- 偏置项权重还原:w_0 为迭代后偏置项的权重。
输入描述
- 第一行:整数 m(样本数量)
- 第二行:整数 N(迭代次数)
- 第三行:浮点数 α(学习率,保留 2 位小数)
- 后续 m 行:每行 4 个整数,依次为 x1(协议连接数)、x2(转发数据包速率)、x3(内存占用率)、y(资源用量)
输出描述
一行,4 个浮点数,依次为还原后的 w_0'、w_1'、w_2'、w_3',结果保留 2 位小数,银行家舍入,以一个空格分隔,前后无冗余空格。
样例输入 1
3 100 0.10 100 200 150 6000 200 800 600 7500 300 70 60 6500
样例输出 1
4394.59 6.82 1.20 1.55
样例输入 2
2 50 0.05 0 0 0 0 1000 10000 100 100000
样例输出 2
11419.33 28.26 2.83 282.62
参考题解
解题思路:
本题考察监督学习中线性回归的实现,核心步骤为:
- 特征归一化:对每个特征维度,按照 Min-Max 归一化将数据缩放到 [0, 1] 区间,加快梯度下降的收敛速度。对无波动特征(max == min)直接置 0 避免除零。
- 批量梯度下降(BGD):每一轮用全部样本计算梯度的累加和,再除以 m 求平均,最后按学习率 α 同步更新偏置和三个特征权重。固定迭代 N 次不做收敛判断。
- 权重还原:由于训练时使用的是归一化后的特征,输出时要把权重换回原始尺度——各特征权重除以原始区间 (x_max - x_min);偏置项减去 Σ w_j' · x_min_j 以抵消归一化时的平移量。
- 银行家舍入:即"四舍六入五成双",对 .5 的情况取偶数。Python 的内置
round()默认就是银行家舍入;Java 可用BigDecimal.ROUND_HALF_EVEN;C++ 需要手工实现。
C++:
#include <iostream>
#include <vector>
#include <cmath>
#include <iomanip>
#include <sstream>
#include <algorithm>
using namespace std;
// 银行家舍入(四舍六入五成双)保留 decimals 位小数
double bankerRound(double value, int decimals) {
double factor = pow(10.0, decimals);
double scaled = value * factor;
double floorVal = floor(scaled);
double diff = scaled - floorVal;
double rounded;
const double EPS = 1e-9;
if (diff < 0.5 - EPS) {
rounded = floorVal;
} else if (diff > 0.5 + EPS) {
rounded = floorVal + 1.0;
} else {
// 恰好 0.5,向偶数舍入
long long fi = (long long) floorVal;
if (fi % 2 == 0) rounded = floorVal;
else rounded = floorVal + 1.0;
}
return rounded / factor;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);
int m, N;
double alpha;
cin >> m >> N >> alpha;
vector<vector<double>> X(m, vector<double>(3));
vector<double> Y(m);
for (int i = 0; i < m; i++) {
cin >> X[i][0] >> X[i][1] >> X[i][2] >> Y[i];
}
// 1. 特征归一化
vector<double> X_min(3), X_max(3);
for (int j = 0; j < 3; j++) {
X_min[j] = X_max[j] = X[0][j];
for (int i = 1; i < m; i++) {
X_min[j] = min(X_min[j], X[i][j]);
X_max[j] = max(X_max[j], X[i][j]);
}
}
vector<vector<double>> X_norm(m, vector<double>(3, 0.0));
for (int i = 0; i < m; i++) {
for (int j = 0; j < 3; j++) {
if (X_max[j] == X_min[j]) X_norm[i][j] = 0.0;
else X_norm[i][j] = (X[i][j] - X_min[j]) / (X_max[j] - X_min[j]);
}
}
// 2. 批量梯度下降
vector<double> w(4, 0.0);
for (int it = 0; it < N; it++) {
vector<double> grad(4, 0.0);
for (int i = 0; i < m; i++) {
double y_hat = w[0]
+ w[1] * X_norm[i][0]
+ w[2] * X_norm[i][1]
+ w[3] * X_norm[i][2];
double diff = y_hat - Y[i];
grad[0] += diff;
grad[1] += diff * X_norm[i][0];
grad[2] += diff * X_norm[i][1];
grad[3] += diff * X_norm[i][2];
}
for (int j = 0; j < 4; j++) {
w[j] -= alpha * (grad[j] / m);
}
}
// 3. 特征权重及偏置项还原
vector<double> wp(4, 0.0);
for (int j = 1; j < 4; j++) {
if (X_max[j-1] == X_min[j-1]) wp[j] = 0.0;
else wp[j] = w[j] / (X_max[j-1] - X_min[j-1]);
}
wp[0] = w[0] - (wp[1] * X_min[0] + wp[2] * X_min[1] + wp[3] * X_min[2]);
// 4. 输出(银行家舍入保留 2 位小数)
for (int i = 0; i < 4; i++) {
if (i) cout << " ";
cout << fixed << setprecision(2) << bankerRound(wp[i], 2);
}
cout << "\n";
return 0;
}
Java:
import java.io.*;
import java.util.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int m = Integer.parseInt(br.readLine().trim());
int N = Integer.parseInt(br.readLine().trim());
double alpha = Double.parseDouble(br.readLine().trim());
double[][] X = new double[m][3];
double[] Y = new double[m];
for (int i = 0; i < m; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
X[i][0] = Double.parseDouble(st.nextToken());
X[i][1] = Double.parseDouble(st.nextToken());
X[i][2] = Double.parseDouble(st.nextToken());
Y[i] = Double.parseDouble(st.nextToken());
}
// 1. 特征归一化
double[] X_min = new double[3];
double[] X_max = new double[3];
for (int j = 0; j < 3; j++) {
X_min[j] = X[0][j]; X_max[j] = X[0][j];
for (int i = 1; i < m; i++) {
X_min[j] = Math.min(X_min[j], X[i][j]);
X_max[j] = Math.max(X_max[j], X[i][j]);
}
}
double[][] Xn = new double[m][3];
for (int i = 0; i < m; i++) {
for (int j = 0; j < 3; j++) {
if (X_max[j] == X_min[j]) Xn[i][j] = 0.0;
else Xn[i][j] = (X[i][j] - X_min[j]) / (X_max[j] - X_min[j]);
}
}
// 2. 批量梯度下降
double[] w = new double[4];
for (int it = 0; it < N; it++) {
double[] grad = new double[4];
for (int i = 0; i < m; i++) {
double y_hat = w[0] + w[1]*Xn[i][0] + w[2]*Xn[i][1] + w[3]*Xn[i][2];
double diff = y_hat - Y[i];
grad[0] += diff;
grad[1] += diff * Xn[i][0];
grad[2] += diff * Xn[i][1];
grad[3] += diff * Xn[i][2];
}
for (int j = 0; j < 4; j++) {
w[j] -= alpha * (grad[j] / m);
}
}
// 3. 特征权重及偏置项还原
double[] wp = new double[4];
for (int j = 1; j < 4; j++) {
if (X_max[j-1] == X_min[j-1]) wp[j] = 0.0;
else wp[j] = w[j] / (X_max[j-1] - X_min[j-1]);
}
wp[0] = w[0] - (wp[1]*X_min[0] + wp[2]*X_min[1] + wp[3]*X_min[2]);
// 4. 银行家舍入输出(HALF_EVEN)
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 4; i++) {
BigDecimal bd = new BigDecimal(Double.toString(wp[i]))
.setScale(2, RoundingMode.HALF_EVEN);
if (i > 0) sb.append(' ');
sb.append(bd.toPlainString());
}
System.out.println(sb);
}
}
Python:
import sys
def solve():
m = int(sys.stdin.readline().strip())
N = int(sys.stdin.readline().strip())
alpha = float(sys.stdin.readline().strip())
X = []
Y = []
# 循环读取 m 行样本数据
for _ in range(m):
parts = sys.stdin.readline().strip().split()
if parts:
X.append([float(parts[0]), float(parts[1]), float(parts[2])])
Y.append(float(parts[3]))
# 1. 特征归一化
X_min = [min(X[i][j] for i in range(m)) for j in range(3)]
X_max = [max(X[i][j] for i in range(m)) for j in range(3)]
X_norm = [[0.0] * 3 for _ in range(m)]
for i in range(m):
for j in range(3):
if X_max[j] == X_min[j]:
X_norm[i][j] = 0.0
else:
X_norm[i][j] = (X[i][j] - X_min[j]) / (X_max[j] - X_min[j])
# 2. 批量梯度下降�代
w = [0.0, 0.0, 0.0, 0.0] # w0, w1, w2
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
2025 春招笔试合集 文章被收录于专栏
2025打怪升级记录,大厂笔试合集 C++, Java, Python等多种语言做法集合指南
查看6道真题和解析