阿里高德笔试 高德笔试 0403
笔试时间:2025年04月03日
历史笔试传送门:
第一题
题目
假设你正在开发地图数据校验工具,其中有一个功能是检测城市的道路网络是否连通。具体来说,就是判断从任何一个地点出发,能否通过现有的道路到达其他任何地点。为此,我们需要设计一个算法来验证这一点。
输入描述
第一行包含两个整数 n 和 m,分别表示城市中有多少个地点以及有多少条双向道路。每个地点都有唯一的编号,范围是 [1, n]。
接下来 m 行,每行包含两个整数 a 和 b,表示地点 a 和地点 b 之间有一条双向道路相连。
输出描述
输出一行字符串,如果城市的所有地点都是相互连通的,则输出 "Yes";否则,输出 "No"。
样例输入
5 6
0 1
0 2
1 3
2 3
3 4
1 4
样例输出
Yes
参考题解
用 邻接表(List) 存储图结构:graph[i] 存储 与地点 i 相连的所有地点。构建图。读取 m 条边,每条边连接 a 和 b,表示地点 a 和 b 之间有道路:由于是 无向图,所以 graph[a].add(b) 和 graph[b].add(a) 都需要添加。深度优先搜索(DFS)遍历。使用 visited[] 数组 记录哪些节点被访问过。从 0 号节点 开始执行 DFS,递归访问所有能到达的节点。判断连通性。遍历 visited[] 数组,检查是否所有节点都被访问:若 visited[i] == false(有未访问的节点),说明图不连通,输出 "No"。否则,输出 "Yes",表示所有节点都能相互到达。
C++:[此代码未进行大量数据的测试,仅供参考]
#include <iostream> #include <vector> using namespace std; void dfs(const vector<vector<int>>& graph, int node, vector<bool>& visited) { visited[node] = true; for (int neighbor : graph[node]) { if (!visited[neighbor]) { dfs(graph, neighbor, visited); } } } int main() { int n, m; cin >> n >> m; vector<vector<int>> graph(n); for (int i = 0; i < m; i++) { int a, b; cin >> a >> b; graph[a].push_back(b); graph[b].push_back(a); } vector<bool> visited(n, false); dfs(graph, 0, visited); bool isConnected = true; for (int i = 0; i < n; i++) { if (!visited[i]) { isConnected = false; break; } } cout << (isConnected ? "Yes" : "No") << endl; return 0; }
Java:[此代码未进行大量数据的测试,仅供参考]
import java.util.*; public class MapDataVerification { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); // 读取地点数量和道路数量 int n = scanner.nextInt(); int m = scanner.nextInt(); // 构建邻接表表示图 List<List<Integer>> graph = new ArrayList<>(); for (int i = 0; i < n; i++) { graph.add(new ArrayList<>()); } // 读取每条道路的信息并添加到图中 for (int i = 0; i < m; i++) { int a = scanner.nextInt(); int b = scanner.nextInt(); graph.get(a).add(b); graph.get(b).add(a); } // 标记节点是否被访问过 boolean[] visited = new boolean[n]; // 从节点 0 开始深度优先搜索 dfs(graph, 0, visited); // 检查是否所有节点都被访问过 boolean isConnected = true; for (int i = 0; i < n; i++) { if (!visited[i]) { isConnected = false; break; } } // 输出结果 System.out.println(isConnected ? "Yes" : "No"); } private static void dfs(List<List<Integer>> graph, int node, boolean[] visited) { // 标记当前节点为已访问 visited[node] = true; // 遍历当前节点的所有邻居节点 for (int neighbor : graph.get(node)) { if (!visited[neighbor]) { dfs(graph, neighbor, visited); } } } }
Python:[此代码未进行大量数据的测试,仅供参考]
def dfs(graph, node, visited): visited[node] = True for neighbor in graph[node]: if not visited[neighbor]: dfs(graph, neighbor, visited) def main(): n, m = map(int, input().split()) graph = [[] for _ in range(n)] for _ in range(m): a, b = map(int, input().split()) graph[a].append(b) graph[b].append(a) visited = [False] * n dfs(graph, 0, visited) is_connected = all(visited) print("Yes" if is_connected else "No") if __name__ == "__main__": main()
第二题
题目
在导航app中,实现为用户推荐最近的3个充电桩的功能,需求如下:
给出用户所在位置,以及N个备选充电桩位置,返回距离用户最近且距离小于3km的前3个充电桩。
输入描述
第一行包含两个整数n和m,分别表示有向图中有多少个点以及有多少条边。每个点都有唯一的编号,范围是[0, n]。
第二行包含一个整数,为用户所在NodeID。
第三行包含一个整数k,为备选充电桩个数。
接下来k行,每行一个整数,为备选充电桩所在NodeID。
接下来m行,每行包含三个整数a、b、w,表示点a和点b之间有一条单向边,权重为w(单位米)。
输出描述
最近的充电桩的NodeID和距离,用"NodeID,Distance"表达,多个桩以";"分隔,若没有结果则返回"None" 。
样例输入
6 8
0
3
2
3
5
0 1 100
1 2 150
2 3 300
3 4 200
0 4 200
4 5 100
5 3 200
1 4 100
2 5 200
样例输出
2,2500;5,3000;3,3500
参考题解
构建图数据结构用 List<List<Edge>> 存储有向图,每个点存储连接的边(邻接表)。读取 m 条边的信息,建立图结构。Dijkstra 算法求最短路径使用 优先队列(堆) 维护当前最短路径。遍历所有可达点,更新到达该点的最短路径。筛选 & 排序筛选出 距离小于 3000m 的充电桩。按 距离升序排序,取 最近的 3 个。格式化输出按 NodeID,Distance 形式输出,多个桩用 ; 分隔。若无满足条件的充电桩,返回 "None"。复杂度分析Dijkstra 算法:O((N + M) log N),N 是点数,M 是边数。充电桩筛选 & 排序:O(K log K),K 是充电桩数。总体复杂度 ≈ O((N + M) log N) + O(K log K),适用于 大规模地图数据。
C++:[此代码未进行大量数据的测试,仅供参考]
#include <iostream> #include <vector> #include <queue> #include <unordered_set> #include <unordered_map> #include <algorithm> using namespace std; struct Edge { int to, weight; Edge(int to, int weight) : to(to), weight(weight) {} }; unordered_map<int, int> dijkstra(const vector<vector<Edge>>& graph, int start, int n) { unordered_map<int, int> distances; priority_queue<pair<int, int>, vector<pair<int, int>>, greater<>> pq; pq.push({0, start}); distances[start] = 0; while (!pq.empty()) { auto [dist, node] = pq.top(); pq.pop(); if (dist > distances[node]) continue; for (const auto& edge : graph[node]) { int newDist = dist + edge.weight; if (!distances.count(edge.to) || newDist < distances[edge.to]) { distances[edge.to] = newDist; pq.push({newDist, edge.to}); } } } return distances; } int main() { int n, m, userNode, k; cin >> n >> m >> userNode >> k; unordered_set<int> chargers; for (int i = 0; i < k; i++) { int charger; cin >> charger; chargers.insert(charger); } vector<vector<Edge>> graph(n); for (int i = 0; i < m; i++) { int a, b, w; cin >> a >> b >> w; graph[a].emplace_back(b, w); } auto distances = dijkstra(graph, userNode, n); vector<pair<int, int>> results; for (int charg
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
2025打怪升级记录,大厂笔试合集 C++, Java, Python等多种语言做法集合指南