饿了么笔试 饿了么笔试题 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等多种语言做法集合指南

查看19道真题和解析