【秋招笔试】2025.08.02-OPPO秋招第三套改编题
✅ 秋招备战指南 ✅
💡 学习建议:
- 先尝试独立解题
- 对照解析查漏补缺
🧸 题面描述背景等均已深度改编,做法和题目本质基本保持一致。
🍹 感谢各位朋友们的订阅,你们的支持是我们创作的最大动力
🌸 目前本专栏已经上线100+套真题改编解析,后续会持续更新的
春秋招笔试机考招合集 -> 互联网必备刷题宝典🔗
题目一:小兰的团队分配
1️⃣:对员工能力值进行排序,将最小和最大的n/3个员工分别分组
2️⃣:利用数学公式 max(2z-x-y, z+y-2x) 计算最终答案
难度:中等
这道题目的关键在于理解如何最大化项目组之间的能力差异。通过将员工按能力值排序,然后将最强和最弱的员工分别集中到不同组中,可以最大化组间差异。最终问题转化为一个简单的数学公式计算。
题目二:小基的社交网络探索
1️⃣:从编号最小的节点1开始进行DFS遍历
2️⃣:对每个节点的邻接表按编号排序,确保按字典序访问
3️⃣:使用栈模拟DFS,逆序压栈保证正序弹栈
难度:中等
这道题目结合了图论遍历和字典序优化。关键在于理解DFS的访问顺序如何影响最终序列的字典序,通过合理的数据结构设计和访问策略,可以得到最优的遍历序列。
题目三:小毛的游戏机调试
1️⃣:使用并查集将对称位置的数字连接成连通块
2️⃣:统计每个连通块中状态为0和1的数字个数
3️⃣:对每个连通块取min(count0, count1)作为最优翻转次数
难度:中等偏难
这道题目需要理解回文约束与操作特性的关系,并设计高效的数据结构来处理等价关系。通过并查集将相关的数字分组,然后对每组独立计算最优策略,实现了 O(n α(n)) 的高效解法。
01. 小兰的团队分配
问题描述
小兰是一家科技公司的项目经理,她需要将公司的 名员工分配到三个不同的项目组中。每个员工都有一个能力值
,现在小兰希望将这些员工平均分配到三个项目组中,使得每个项目组的人数都相同。
设第 个项目组的总能力值为
(
),小兰希望最大化以下表达式的值:
这个表达式反映了项目组之间能力差异的程度,小兰认为适度的能力差异有助于形成良性竞争。
输入格式
第一行包含一个正整数 (
),表示员工数量,保证
是 3 的倍数。
第二行包含 个正整数
(
),表示每个员工的能力值。
输出格式
输出一个整数,表示表达式 的最大可能值。
样例输入
3
1 2 3
样例输出
3
数据范围
是 3 的倍数
样例 | 解释说明 |
---|---|
样例1 | 将三个员工分别单独分成三组,能力值分别为 1、2、3。重新编号为 |
题解
这道题的关键在于理解如何分配员工才能让项目组之间的能力差异最大化。
首先分析问题的本质:我们需要将 个数分成三组,每组
个数,使得
最大。
为了让这个表达式最大,直观的想法是让三组的能力值尽可能分散。具体来说:
- 将能力值最小的
个员工分到一组
- 将能力值最大的
个员工分到一组
- 将剩余的员工分到第三组
设三组的能力值按从小到大排序后分别为 ,那么对于任意的
的排列,表达式
的最大值为:
这是因为当 是最大值或最小值时,表达式能取到最大值。
算法步骤:
- 对所有员工的能力值进行排序
- 计算最小组(前
个)的能力总和
- 计算最大组(后
个)的能力总和
- 计算中间组的能力总和
- 应用公式计算答案
时间复杂度为 ,主要来自排序操作。
参考代码
- Python
import sys
input = lambda: sys.stdin.readline().strip()
def solve():
n = int(input())
a = list(map(int, input().split()))
# 排序获得有序的能力值列表
a.sort()
k = n // 3
# 计算三组的能力总和
low_sum = sum(a[:k]) # 最小组:前k个
high_sum = sum(a[-k:]) # 最大组:后k个
mid_sum = sum(a) - low_sum - high_sum # 中间组:剩余的
# 应用公式计算最大值
ans = max(2 * high_sum - low_sum - mid_sum,
high_sum + mid_sum - 2 * low_sum)
print(ans)
if __name__ == "__main__":
solve()
- Cpp
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<long long> a(n);
// 读入员工能力值
for (int i = 0; i < n; i++) {
cin >> a[i];
}
// 排序以便分组
sort(a.begin(), a.end());
int k = n / 3;
// 计算各组能力总和
long long low = 0, high = 0, total = 0;
for (int i = 0; i < n; i++) {
total += a[i];
if (i < k) low += a[i]; // 最小组
if (i >= n - k) high += a[i]; // 最大组
}
long long mid = total - low - high; // 中间组
// 计算表达式的最大值
long long res = max(2 * high - low - mid, high + mid - 2 * low);
cout << res << '\n';
return 0;
}
- Java
import java.util.*;
import java.io.*;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
String[] line = br.readLine().split(" ");
long[] a = new long[n];
// 读取员工能力值
for (int i = 0; i < n; i++) {
a[i] = Long.parseLong(line[i]);
}
// 对能力值排序
Arrays.sort(a);
int k = n / 3;
// 计算三组的总能力值
long lowSum = 0, highSum = 0, totalSum = 0;
for (int i = 0; i < n; i++) {
totalSum += a[i];
if (i < k) lowSum += a[i]; // 最小的k个
if (i >= n - k) highSum += a[i]; // 最大的k个
}
long midSum = totalSum - lowSum - highSum;
// 根据公式计算答案
long answer = Math.max(2 * highSum - lowSum - midSum,
highSum + midSum - 2 * lowSum);
System.out.println(answer);
}
}
02. 小基的社交网络探索
问题描述
小基是一位数据分析师,她正在研究一个包含 个用户的社交网络。在这个网络中,用户之间通过友谊关系相互连接,形成了一个连通的社交网络图,其中用户编号为
到
。
小基想要通过深度优先搜索(DFS)的方式来分析这个社交网络的结构。她可以从任意用户开始探索,每当访问一个用户时,可以选择以任意顺序访问该用户的所有好友。小基希望得到字典序最小的用户访问序列,以便进行后续的数据分析。
深度优先搜索(DFS):从指定用户开始,每次选择一个未访问过的好友继续探索,直到所有可达用户都被访问。
访问序列:DFS过程中访问用户的编号序列。
字典序:比较两个序列时,从第一个元素开始逐一比较,直到出现不同元素,通过该位置的元素大小确定字典序。
输入格式
第一行包含一个正整数 (
),表示社交网络中的用户数量。
接下来 行,每行包含两个正整数
(
,
),表示用户
和用户
之间存在友谊关系。
输出格式
输出一行包含 个正整数,用空格分隔,表示字典序最小的用户访问序列。
样例输入
5
1 2
1 3
2 4
2 5
6
1 3
1 2
2 5
2 4
5 6
样例输出
1 2 4 5 3
1 2 4 5 6 3
数据范围
,
- 保证输入构成一棵树
样例 | 解释说明 |
---|---|
样例1 | 从用户1开始,先访问好友2(比3小),再从用户2访问好友4、5(按编号顺序),最后回到用户1访问好友3 |
样例2 | 从用户1开始访问好友2,然后依次访问4、5、6,最后访问用户3,形成字典序最小的访问序列 |
题解
这道题要求找到树上字典序最小的DFS序列。关键在于理解如何选择起点和访问顺序。
首先分析策略:
- 选择起点:序列的第一个元素就是起点,显然应该选择编号最小的节点1作为起点
- 访问顺序:对于每个节点,应该按照编号从小到大的顺序访问其未访问过的邻居节点
具体实现时需要注意:
- 对每个节点的邻接表进行排序,确保按编号顺序访问
- 使用非递归的栈模拟DFS,避免在
时递归栈溢出
- 将子节点按逆序压栈,这样弹栈时就是正序访问
算法步骤:
- 构建邻接表并对每个节点的邻居列表排序
- 使用栈从节点1开始进行DFS
- 每次弹出一个节点时,将其加入结果序列
- 按逆序将该节点的未访问邻居压入栈中
时间复杂度 (主要来自排序),空间复杂度
。
参考代码
- Python
import sys
input = lambda: sys.stdin.readline().strip()
def solve():
n = int(input())
# 构建邻接表
graph = [[] for _ in range(n + 1)]
for _ in range(n - 1):
u, v = map(int, input().split())
graph[u].append(v)
graph[v].append(u)
# 对每个节点的邻居列表排序
for i in range(1, n + 1):
graph[i].sort()
# 使用栈进行DFS
visited = [False] * (n + 1)
stack = [1] # 从节点1开始
result = []
while stack:
node = stack.pop()
if visited[node]:
continue
visited[node] = True
result.append(node)
# 逆序压栈,保证弹栈时按正序访问
for neighbor in reversed(graph[node]):
if not visited[neighbor]:
stack.append(neighbor)
print(' '.join(map(str, result)))
if __name__ == "__main__":
solve()
- Cpp
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
// 构建邻接表
vector<vector<int>> adj(n + 1);
for (int i = 0; i < n - 1; i++) {
int u, v;
cin >> u >> v;
adj[u].push_back(v);
adj[v].push_back(u);
}
// 对邻接表排序
for (int i = 1; i <= n; i++) {
sort(adj[i].begin(), adj[i].e
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
互联网刷题笔试宝典,这里涵盖了市面上大部分的笔试题合集,希望助大家春秋招一臂之力