饿了么笔试 饿了么笔试题 0829
笔试时间:2025年8月29日
往年笔试合集:
第一题
小红给定一个大小为n×m的矩阵A,从上往下为第i行,从左往右为第j列,元素为Aᵢ,ⱼ。
每次操作可以选择两个不相邻的元素交换(即选定两个坐标(i₁, j₁)和(i₂, j₂)满足|i₁ - i₂| + |j₁ - j₂| ≠ 1),然后交换这两个位置的元素值。
目标:在所有操作结果中,找到矩阵字典序最大的元素分布。
矩阵字典序定义:
两个大小为n×m的矩阵p和q:
- 从第1行到第n行,第1列到第m列依次比较。
- 当某个位置pᵢ,ⱼ > qᵢ,ⱼ,则p的字典序大于q;
- 若pᵢ,ⱼ < qᵢ,ⱼ,则p的字典序小于q;
- 若相等则继续比较,直到全部一致则字典序相等。
输入描述
第一行两个整数 n,m(2 ≤ n,m ≤ 500),表示矩阵的行列大小。
接下来 n 行,每行 m 个元素,表示矩阵 A 的元素(1 ≤ Aᵢ,ⱼ ≤ 10⁹)。
输出描述
输出 n 行 m 列,表示在所有操作结果中,字典序最大的元素分布。
样例输入
2 3
1 2 3
4 5 6
样例输出
6 5 4
3 2 1
参考题解
当矩阵的元素个数大于等于 4 时,相当于我可以重排整个矩阵,那么直接排序即可,否则就是 2*2 ,特殊处理下即可。
C++:
#include <bits/stdc++.h> using namespace std; int main() { int n, m; cin >> n >> m; vector<vector<int>> a(n + 10, vector<int>(m + 10)); vector<int> ans; for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { cin >> a[i][j]; ans.push_back(a[i][j]); } } if (n * m >= 5) { sort(ans.begin(), ans.end()); for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { cout << ans.back() << " "; ans.pop_back(); } cout << '\n'; } } else { if (a[1][1] < a[2][2]) { swap(a[1][1], a[2][2]); } if (a[1][2] < a[2][1]) { swap(a[1][2], a[2][1]); } for (int i = 1; i <= n; i++) { for (int j = 1; j <= m; j++) { cout << a[i][j] << " "; } cout << '\n'; } } return 0; }
Java:
import java.util.*; public class ArrayProcessor { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); int m = scanner.nextInt(); int[][] a = new int[n][m]; List<Integer> ans = new ArrayList<>(); // 读取二维数组并收集所有元素 for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { a[i][j] = scanner.nextInt(); ans.add(a[i][j]); } } int total = n * m; if (total >= 5) { // 元素总数不少于5时,排序后从大到小输出 Collections.sort(ans); // 升序排序 Collections.reverse(ans); // 反转为降序 int idx = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { System.out.print(ans.get(idx) + " "); idx++; } System.out.println(); } } else { // 元素总数少于5时,进行特定位置交换后输出 // 注意:原C++代码使用1-based索引,这里转换为0-based索引 // 交换a[1][1]和a[2][2](对应0-based的a[0][0]和a[1][1]) if (n >= 2 && m >= 2 && a[0][0] < a[1][1]) { int temp = a[0][0]; a[0][0] = a[1][1]; a[1][1] = temp; } // 交换a[1][2]和a[2][1](对应0-based的a[0][1]和a[1][0]) if (n >= 2 && m >= 2 && a[0][1] < a[1][0]) { int temp = a[0][1]; a[0][1] = a[1][0]; a[1][0] = temp; } // 输出处理后的数组 for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { System.out.print(a[i][j] + " "); } System.out.println(); } } scanner.close(); } }
Python:
n, m = map(int, input().split()) a = [] ans = [] # 读取二维数组并收集所有元素 for _ in range(n): row = list(map(int, input().split())) a.append(row) ans.extend(row) total = n * m if total >= 5: # 元素总数不少于5时,排序后从大到小输出 ans.sort() # 升序排序 idx = len(ans) - 1 # 从最后一个元素开始(最大元素) for i in range(n): row_output = [] for j in range(m): row_output.append(str(ans[idx])) idx -= 1 print(' '.join(row_output)) else: # 元素总数少于5时,进行特定位置交换后输出 # 注意:原C++代码使用1-based索引,这里转换为0-based索引 # 交换a[1][1]和a[2][2](对应0-based的a[0][0]和a[1][1]) if n >= 2 and m >= 2 and a[0][0] < a[1][1]: a[0][0], a[1][1] = a[1][1], a[0][0] # 交换a[1][2]和a[2][1](对应0-based的a[0][1]和a[1][0]) if n >= 2 and m >= 2 and a[0][1] < a[1][0]: a[0][1], a[1][0] = a[1][0], a[0][1] # 输出处理后的数组 for row in a: print(' '.join(map(str, row)))
第二题
定义两个长度为n的排列x,y相似,当且仅当对于除区间1≤l≤r≤n,都有下式成立:
现在小红拿到了一个长为n的排列a,请你构造一个与a相似的排列。
【名词解释】长度为n的排列:由1,2,···,n这n个整数、按任意顺序组成的数组(每个整数均恰好出现一次)。例如,{2,3,1,5,4}是一个长度为5的排列,而{1,2,2}和{1,3,4}都不是排列,因为前者存在重复元素,后者包含了超出范围的数。
输入描述
每个测试文件均包含多组测试数据。第一行输入一个整数T(1≤T≤10³)代表数据组数,每组测试数据描述如下: 第一行输入一个整数n(1≤n≤2×10⁴),表示排列的长度。 第二行输入n个两两不同的整数a₁,a₂,⋯,aₙ(1≤aᵢ≤n),表示排列中的元素。 除此之外,保证单个测试文件的n之和不超过2×10⁵。
输出描述
对于每一组测试数据,新起一行输出n个数,代表所构造的排列。 如果存在多个解决方案,您可以输出任意一个,系统会自动判定是否正确。注意,自测运行功能可能因此返回错误结果,请自行检查答案正确性。
样例输入
2 4
1 2 3 4
4
2 1 3 4
样例输出
4 3 1 2
1 3 4 2
参考题解
C++:
#include <
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
2025打怪升级记录,大厂笔试合集 C++, Java, Python等多种语言做法集合指南