饿了么笔试 饿了么秋招 0905
笔试时间:2025年9月5日
往年笔试合集:
第一题:城市公路维修时间
题目描述: 城市公路某些路段路面质量下降,多多需要对这些路段进行维修。多多可进行工作的时间为H。同时有交通管理系统会根据不同因素发出拥堵预警。多多的维修应当在路况不繁忙的时候进行,需要注意预警时段可能存在重叠。请你帮助多多计算可以进行公路维修的时间共有多少。
输入描述
第一行为一个整数T,表示共有T个测试数据,且1≤T≤100
每组测试数据:
第一行为一个整数H,表示多多可进行维修的工作总时长,且1≤H≤10^9
第二行为一个整数N,表示预警时段的个数,且0≤N≤10^5
接下来的N行,每行输入两个整数li, ri,表示区间[li,ri]被预警将有拥堵发生,且1≤li≤ri≤H
输出描述
每组数据输出一个结果,每个结果占一行。
样例输入
1
10
2
5 10
5 5
样例输出
4
参考题解
把所有拥堵预警区间做并集,求出被占用的总时长,再用可工作总时长H减去它即可。先按起点对所有区间排序,然后扫描合并重叠区间,最后计算预警总时长。
C++:
#include <iostream> #include <vector> #include <algorithm> using namespace std; void solve() { int T; cin >> T; while (T--) { int H, N; cin >> H >> N; vector<pair<int, int>> intervals(N); for (int i = 0; i < N; i++) { cin >> intervals[i].first >> intervals[i].second; } if (intervals.empty()) { cout << H << endl; continue; } sort(intervals.begin(), intervals.end()); vector<pair<int, int>> merged; int l = intervals[0].first, r = intervals[0].second; for (int i = 1; i < N; i++) { int x = intervals[i].first, y = intervals[i].second; if (x <= r) { r = max(r, y); } else { merged.push_back({l, r}); l = x; r = y; } } merged.push_back({l, r}); long long blocked = 0; for (auto& p : merged) { blocked += p.second - p.first + 1; } cout << H - blocked << endl; } } int main() { solve(); return 0; }
Java:
import java.util.*; public class Solution { public static void solve() { Scanner sc = new Scanner(System.in); int T = sc.nextInt(); while (T-- > 0) { int H = sc.nextInt(); int N = sc.nextInt(); List<int[]> intervals = new ArrayList<>(); for (int i = 0; i < N; i++) { int l = sc.nextInt(); int r = sc.nextInt(); intervals.add(new int[]{l, r}); } if (intervals.isEmpty()) { System.out.println(H); continue; } intervals.sort((a, b) -> a[0] - b[0]); List<int[]> merged = new ArrayList<>(); int l = intervals.get(0)[0], r = intervals.get(0)[1]; for (int i = 1; i < N; i++) { int x = intervals.get(i)[0]; int y = intervals.get(i)[1]; if (x <= r) { r = Math.max(r, y); } else { merged.add(new int[]{l, r}); l = x; r = y; } } merged.add(new int[]{l, r}); long blocked = 0; for (int[] p : merged) { blocked += p[1] - p[0] + 1; } System.out.println(H - blocked); } } public static void main(String[] args) { solve(); } }
Python:
def solve(): import sys input = sys.stdin.readline T = int(input().strip()) for _ in range(T): H = int(input().strip()) N = int(input().strip()) intervals = [tuple(map(int, input().split())) for _ in range(N)] if not intervals: print(H) continue # 按起点排序 intervals.sort() merged = [] l, r = intervals[0] for x, y in intervals[1:]: if x <= r: # 有交集,合并 r = max(r, y) else: # 无交集,保存 merged.append((l, r)) l, r = x, y merged.append((l, r)) # 计算预警总时长 blocked = sum(r - l + 1 for l, r in merged) print(H - blocked) solve()
第二题:魔法森林传送门
题目描述: 在一片神奇的魔法森林中,有n个魔法节点,每个节点都有一个传送门。第i个节点的传送门会把你传送到a[i]号节点。多多每次可以选择坐传送门从i节点传送到a[i]节点,或者选择步行到相邻的节点i-1或i+1节点。现在多多从1号节点出发,想知道到达每个节点需要经过的最少步行次数。
输入描述
输入两行,第一行包含一个数字n,表示有n个节点(1≤n≤10^5)
接下来一行n个数字,每个数字a[i](1≤a[i]≤n),表示第i节点的传送门可以传送到a[i]节点
输出描述
输出一行包含n个数字,第i个数字表示从1号节点到i号节点的最少步行次数。
样例输入
3
1 2 3
样例输出
0 1 2
参考题解
这是一个0-1 BFS问题。传送门不需要步行(代价为0),走到相邻节点需要一步(代价为1)。使用双端队列,代价为0的边用appendleft,代价为1的边用append。
C++:
#include <iostream> #include <vector> #include <deque> using namespace std; void solve() { int n; cin >> n; vector<int> a(n + 1); for (int i = 1; i <= n; i++) { cin >> a[i]; } vector<int> dist(n + 1, 1e9); dist[1] = 0; deque<int> q; q.push_back(1); while (!q.empty()) { int x = q.front(); q.pop_front(); // 传送门(权重0) int y = a[x]; if (dist[y] > dist[x]) { dist[y] = dist[x]; q.push_front(y); } // 步行到相邻节点(权重1) if (x > 1 && dist[x - 1] > dist[x] + 1) { dist[x - 1] = dist[x] + 1; q.push
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
2025打怪升级记录,大厂笔试合集 C++, Java, Python等多种语言做法集合指南