华为笔试 华为笔试题 0507
笔试时间:2025年5月7日
往年笔试合集:
第一题:寻找智能汽车行驶距离最近的K个充电桩
一个超大智能汽车测试场有多个充电桩,每个充电桩的位置由其在二维平面上的坐标 (x, y) 表示。给定一辆智能汽车的当前位置 (car_x, car_y),请设计一个高效的算法,找出给定智能汽车行驶到充电桩行驶距离最近的k个充电桩并输出相关充电桩信息(编号、坐标、行驶距离),且按行驶距离升序排序(最近行驶距离的排在最前面),如果存在行驶距离相等的充电桩则按照充电桩的编号从小到大输出。汽车到充电桩的行驶距离的计算方法为 abs(car_x - x) + abs(car_y - y) 注意:abs表示绝对值。
输入描述
第一行是2个整数k n,空格间隔,第1个整数k表示需要输出到的行驶距离最近的充电桩的数量( 0 <= k <= 1000000),第2个整数n表示充电桩的总数量(0 < n <= 1000000)。
第2行是长度为2的整数数组car_x car_y,中间是空格间隔,表示智能汽车的当前位置坐标。
第3行到第n+2行是编号为1到n的充电桩的位置坐标。
注意:坐标数值大小区间为: [-2^32, 2^31-1]
输出描述
一个二维数组,每一行是一个长度为4 的数组:编号 x y distance,编号表示充电桩的编号(介于1到n之间)、x y表示充电桩的坐标, distance表示智能汽车到充电桩的行驶距离,从第1行开始往下是按距离从小到大排序的。 如果存在行驶距离相等的充电桩则按照充电桩的编号从小到大输出。如果k为0或者k大于n,输出字符串null。
样例输入
3 5
0 0
1 4
5 6
2 3
7 8
3 -1
样例输出
5 3 -1 4
1 1 4 5
3 2 3 5
解释:到汽车行驶距离最近的三个充电桩的编号分别为5、1、3,充电桩的坐标分别是3 -1、1 4、2 3,到智能汽车坐标[0,0]的行驶距离分别为4、5、5。距离都为5的充电桩1的编号小于编号3的充电桩,输出结果中编号小的在前。
参考题解
数据存储与预处理使用结构体存储每个充电桩的编号、坐标和曼哈顿距离,计算公式为 distance = |car_x - x| + |car_y - y|。所有充电桩信息存入数组,时间复杂度为 *O(n)*。排序策略对充电桩数组进行排序,排序规则为:优先按距离从小到大排序若距离相同,则按编号从小到大排序使用快速排序算法。边界处理若 k=0 或 k>n,直接输出 null;否则截取排序后的前k个元素输出。
C++:
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
int main() {
vector<string> input;
string token;
while (cin >> token) {
input.push_back(token);
}
int ptr = 0;
int k = stoi(input[ptr++]);
int n = stoi(input[ptr++]);
if (k == 0 || k > n) {
cout << "null" << endl;
return 0;
}
int car_x = stoi(input[ptr++]);
int car_y = stoi(input[ptr++]);
vector<tuple<int, int, int, int>> chargers;
for (int i = 0; i < n; i++) {
int x = stoi(input[ptr++]);
int y = stoi(input[ptr++]);
int distance = abs(car_x - x) + abs(car_y - y);
chargers.push_back(make_tuple(distance, i+1, x, y));
}
sort(chargers.begin(), chargers.end(), [](const auto& a, const auto& b) {
if (get<0>(a) != get<0>(b))
return get<0>(a) < get<0>(b);
return get<1>(a) < get<1>(b);
});
for (int i = 0; i < k; i++) {
auto [d, idx, x, y] = chargers[i];
cout << idx << " " << x << " " << y << " " << d << endl;
}
return 0;
}
Java:
import java.util.*;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
List<String> input = new ArrayList<>();
while (scanner.hasNext()) {
input.add(scanner.next());
}
int ptr = 0;
int k = Integer.parseInt(input.get(ptr++));
int n = Integer.parseInt(input.get(ptr++));
if (k == 0 || k > n) {
System.out.println("null");
return;
}
int car_x = Integer.parseInt(input.get(ptr++));
int car_y = Integer.parseInt(input.get(ptr++));
List<Charger> chargers = new ArrayList<>();
for (int i = 0; i < n; i++) {
int x = Integer.parseInt(input.get(ptr++));
int y = Integer.parseInt(input.get(ptr++));
int distance = Math.abs(car_x - x) + Math.abs(car_y - y);
chargers.add(new Charger(distance, i+1, x, y));
}
Collections.sort(chargers, (a, b) -> {
if (a.distance != b.distance)
return a.distance - b.distance;
return a.idx - b.idx;
});
for (int i = 0; i < k; i++) {
Charger c = chargers.get(i);
System.out.printf("%d %d %d %d%n", c.idx, c.x, c.y, c.distance);
}
}
static class Charger {
int distance;
int idx;
int x;
int y;
Charger(int distance, int idx, int x, int y) {
this.distance = distance;
this.idx = idx;
this.x = x;
this.y = y;
}
}
}
Python:
import sys
def main():
input = sys.stdin.read().split()
ptr = 0
k = int(input[ptr])
ptr +=1
n = int(input[ptr])
ptr +=1
if k ==0or k > n:
print("null")
return
car_x = int(input[ptr])
ptr +=1
car_y = int(input[ptr])
ptr +=1
chargers = []
for i in range(n):
x = int(input[ptr])
ptr +=1
y = int(input[ptr])
ptr +=1
distance = abs(car_x - x) + abs(car_y - y)
chargers.append( (distance, i+1, x, y) ) # i+1是编号
# 按距离升序,距离相同按编号升序
chargers.sort(key=lambda x: (x[0], x[1]))
for i in range(k):
d, idx, x, y = chargers[i]
print(f"{idx} {x} {y} {d}")
if __name__ == "__main__":
main()
第二题:建设基站
有一棵二叉树,每个节点上都住了一户居民。现在要给这棵树上的居民建设基站,每个基站只能覆盖她所在与相邻的节点,请问信号覆盖这棵树最少需要建设多少个基站
输入描述
一个整数数组 nums(1<=num.length<=3000),用空格分隔,表示二叉树的节点值,正整数表示存在节点,N 表示不存在节点,如[1 2 3 4 N 5 6]表示一颗如下所示的树,最少需要建设2个基站
输出描述
最少需要建设的基站个数
样例输入
1 2 3 4 N 5 6
样例输出
2
参考题解
树形dp,步骤如下:构建二叉树:根据输入的层序遍历数组构建二叉树结构。递归处理节点:使用深度优先搜索(DFS)递归处理每个节点,计算其三种状态的最小基站数目。状态转移:状态0:当前节点放置基站,覆盖自身及其子节点。状态1:当前节点未被覆盖,需要父节点覆盖,子节点必须被覆盖。状态2:当前节点被覆盖,未放置基站,覆盖来自子节点。结果计算:根节点的最终结果为状态0和状态2的最小值,确保整棵树被覆盖。
C++:
#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <climits>
#include <algorithm>
using namespace std;
struct TreeNode {
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
};
TreeNode* buildTree(const vector<string>& nums) {
if (nums.empty()) return nullptr;
TreeNode* root = new TreeNode(stoi(nums[0]));
queue<TreeNode*> q;
q.push(root);
int i = 1;
while (!q.empty() && i < nums.size()) {
TreeNode* node = q.front(); q.pop();
if (nums[i] != "N") {
node->left = new TreeNode(stoi(nums[i]));
q.push(node->left);
}
i++;
if (i < nums.size() && nums[i] != "N") {
node->right = new TreeNode(stoi(nums[i]));
q.push(node->right);
}
i++;
}
return root;
}
int minStationCover(const vector<string>& nums) {
const int INF = INT_MAX;
function<tuple<int, int, int>(TreeNode*)> dfs = [&](TreeNode* node) {
if (!node) return make_tuple(INF, INF, 0);
auto [l0, l1, l2] = dfs(node->left);
auto [r0, r1, r2] = dfs(node->right);
// 状态0: 当前节点放置基站
int minL0 = min({l0, l1, l2});
int minR0 = min({r0, r1, r2});
int dp0 = 1 + minL0 + minR0;
// 状态1: 当前节点未被覆盖,父节点必须覆盖
int dp1 = l2 + r2;
// 状态2: 当前节点被覆盖,未放置基站,覆盖来自子节点
int option1 = l0 + min(r0, r2);
int option2 = r0 + min(l0, l2);
int option3 = l0 + r0;
int dp2 = min({option1, option2, option3});
return make_tuple(dp0, dp1, dp2);
};
TreeNode* root = buildTree(nums);
if (!root) return 0;
auto [dp0, dp1, dp2] = dfs(root);
return min(dp0, dp2);
}
int main() {
vector<string> nums;
string token;
while (cin >> token) {
nums.push_back(token);
}
cout << minStationCover(nums) << endl;
return 0;
}
Java:
import java.util.*;
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
class Solution {
public static TreeNode buildTree(String[] nums) {
if (nums.length == 0) return null;
TreeNode root = new TreeNode(Integer.parseInt(nums[0]));
Queue<TreeNode> q = new LinkedList<>();
q.add(root);
int i = 1;
while (!q.isEmpty() && i < nums.length) {
TreeNode node = q.poll();
if (!nums[i].equals("N")) {
node.left = new TreeNode(Integer.parseInt(nums[i]));
q.add(node.left);
}
i++;
if (i < nums.length && !n
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
2025打怪升级记录,大厂笔试合集 C++, Java, Python等多种语言做法集合指南
查看9道真题和解析