【春招笔试】2025.04.09-荣耀研发岗真题改编
✅ 春招备战指南 ✅
💡 学习建议:
- 先尝试独立解题(建议用时:90分钟/套)
- 对照解析查漏补缺
🧸 题面描述背景等均已深度改编,做法和题目本质基本保持一致。
🍹 感谢各位朋友们的订阅,你们的支持是我们创作的最大动力
🌸 目前本专栏已经上线60+套真题改编解析,后续会持续更新的
春秋招合集 -> 互联网必备刷题宝典🔗
题目一:优先级军需物资分配问题
1️⃣:遍历数组,贪心选择最合适的子序列放置元素
2️⃣:使用multiset维护各子序列的尾元素和序列ID
3️⃣:寻找尾元素大于当前元素且最小的子序列
难度:中等
这道题目的关键在于理解如何分割数组为最少数量的严格递减子序列。通过贪心策略,每次将元素放入尾部元素刚好大于它的子序列中,可以得到最优解。实现上使用适当的数据结构来高效查找满足条件的子序列。
题目二:珍贵宝石最优收集策略
1️⃣:构建区间动态规划模型解决收集顺序问题
2️⃣:状态定义为移除区间内所有元素能获得的最大收益
3️⃣:考虑每个区间内最后移除的元素,选择最大收益
难度:中等
这道题目需要理解问题可以转化为区间动态规划模型。每次收集一个宝石后,其左右两侧宝石会成为相邻,这种"后效性"使得我们需要考虑所有可能的收集顺序。通过定义合适的状态和转移方程,可以在O(n³)时间内求解。
题目三:星际通讯网络构建
1️⃣:使用广度优先搜索(BFS)寻找网格中的最短路径
2️⃣:检查起点和终点是否可通行
3️⃣:仅允许在信号良好区域铺设线路,标记已访问位置避免重复搜索
难度:中等
这道题目是典型的网格最短路径问题。使用BFS可以保证第一次到达终点时找到的就是最短路径。关键是正确处理网格边界、障碍物(信号差区域),并维护从起点到每个可达位置的距离。时间复杂度为O(n²),适合题目给出的数据范围。
01. 优先级军需物资分配问题
问题描述
小基 王国正处于战争时期,军需处收到了一批急需的军用物资。每件物资都有一个优先级数值,表示军队对该物资的紧急需求程度。为了高效地分配这些物资,军需官小柯决定将物资分成多个运输批次。
由于军队各个单位的特殊要求,每个运输批次中的物资优先级必须呈严格递减顺序,以确保高优先级的物资能够先被分配使用。现在小柯需要你帮忙计算:最少需要分成多少个批次才能将所有物资运送完毕,并列出每个批次中包含的物资优先级。
输入格式
输入一个由逗号分隔的正整数字符串,表示每件物资的优先级。
输出格式
输出运输批次数和各批次物资优先级。 首行输出批次总数,末尾换行。 接下来每行输出一个批次的物资优先级,优先级数值用逗号分隔。
样例输入
7,3,6,2,5,1
样例输出
2
7,3,2,1
6,5
数据范围
- 物资数量不超过 1000
- 物资优先级为正整数,范围为 1 ~ 2147483647
样例 | 物资优先级为 [7,3,6,2,5,1],可以分为两个批次:[7,3,2,1] 和 [6,5],每个批次内的优先级都是严格递减的。注意,不能分为 [7,6,5] 和 [3,2,1] 两个批次,因为批次必须保持原始物资的相对顺序。 |
题解
这道题要求我们将一个数组分割成尽可能少的严格递减子序列。
首先,我们需要理解子序列的概念:子序列是从原序列中选取一些元素,但不改变它们的相对位置而形成的新序列。而且题目要求子序列必须是严格递减的,即每个元素都比前一个元素小。
解题思路是使用贪心算法:
- 遍历原数组中的每个元素
- 对于当前元素,我们尝试将其添加到已有的某个子序列的末尾
- 选择的策略是:找到尾元素大于当前元素且尾元素最小的子序列
- 如果找不到这样的子序列,就新建一个子序列
为什么这个贪心策略是正确的呢?直观上理解,当我们要放置一个新元素时,应该尽量不"浪费"现有子序列中较小的尾元素,而是将新元素放到尽可能合适的位置上。
实现上,我们可以使用一个multiset来维护所有子序列的尾元素及其所属的序列ID,这样可以高效地查找满足条件的子序列。同时,我们需要一个二维数组来记录每个子序列的具体内容。
时间复杂度分析:
- 遍历原数组需要 O(n) 时间
- 每次在multiset中查找和插入操作需要 O(log n) 时间
- 总体时间复杂度为 O(n log n)
对于给定的数据范围(最多1000个元素),这个复杂度是完全可以接受的。
参考代码
- Python
import sys
input = lambda:sys.stdin.readline().strip()
# 读取输入数据
nums_str = input()
nums = list(map(int, nums_str.split(',')))
# 存储所有子序列
seqs = []
# 存储子序列的尾元素及其序列ID:(尾元素, 序列ID)
tails = []
# 遍历原数组中的每个元素
for num in nums:
# 寻找尾元素大于当前元素且尾元素最小的子序列
idx = -1
min_tail = float('inf')
for i, (tail, _) in enumerate(tails):
if tail > num and tail < min_tail:
min_tail = tail
idx = i
if idx == -1:
# 没找到合适的子序列,创建新的
seqs.append([num])
tails.append((num, len(seqs) - 1))
else:
# 将元素加入找到的子序列
seq_id = tails[idx][1]
seqs[seq_id].append(num)
# 更新尾元素
tails[idx] = (num, seq_id)
# 输出结果
print(len(seqs))
for seq in seqs:
print(','.join(map(str, seq)))
- Cpp
#include <iostream>
#include <string>
#include <vector>
#include <set>
#include <sstream>
using namespace std;
int main() {
// 读取输入
string s;
getline(cin, s);
// 解析输入数据
vector<long long> nums;
stringstream ss(s);
string item;
while (getline(ss, item, ',')) {
nums.push_back(stoll(item));
}
// 子序列集合
vector<vector<long long>> seqs;
// 子序列尾元素集合:(尾元素, 序列ID)
multiset<pair<long long, int>> tails;
// 处理每个元素
for (long long x : nums) {
// 找尾元素大于x的最小子序列
auto it = tails.lower_bound(make_pair(x+1, -1));
if (it == tails.end()) {
// 没找到,创建新序列
int id = seqs.size();
seqs.push_back({x});
tails.insert({x, id});
} else {
// 找到了,更新序列
int id = it->second;
tails.erase(it);
seqs[id].push_back(x);
tails.insert({x, id});
}
}
// 输出结果
cout << seqs.size() << endl;
for (auto& seq : seqs) {
for (int i = 0; i < seq.size(); ++i) {
if (i > 0) cout << ",";
cout << seq[i];
}
cout << endl;
}
return 0;
}
- Java
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 读取整行输入
String line = scanner.nextLine();
scanner.close();
// 解析输入数据,按逗号分割
String[] parts = line.split(",");
List<Long> nums = new ArrayList<>();
for (String part : parts) {
nums.add(Long.parseLong(part.trim()));
}
// 子序列列表
List<List<Long>> seqs = new ArrayList<>();
// 使用TreeSet模拟C++ multiset<pair<long long, int>>
// 按尾元素升序排列,若尾元素相同,按序列id升序排列
TreeSet<Pair> tails = new TreeSet<>();
for (long x : nums) {
// 找到第一个尾元素 > x 的子序列
Pair searchKey = new Pair(x + 1, -1);
Pair tail = tails.ceiling(searchKey);
if (tail == null) {
// 没找到,创建新序列
int id = seqs.size();
List<Long> newSeq = new ArrayList<>();
newSeq.add(x);
seqs.add(newSeq);
tails.add(new Pair(x, id));
} else {
// 找到了,更新序列
int id = tail.id;
tails.remove(tail);
seqs.get(id).add(x);
tails.add(new Pair(x, id));
}
}
// 输出结果
System.out.println(seqs.size());
for (List<Long> seq : seqs) {
for (int i = 0; i < seq.size(); i++) {
if (i > 0) System.out.print(",");
System.out.print(seq.get(i));
}
System.out.println();
}
}
// 定义Pair类,实现Comparable接口,用于TreeSet排序
static class Pair implements Comparable<Pair> {
long value;
int id;
Pair(long value, int id) {
this.value = value;
this.id = id;
}
@Override
public int compareTo(Pair other) {
if (this.value != other.value) {
return Long.compare(this.value, other.value);
}
return Integer.compare(this.id, other.id);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Pair)) return false;
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
互联网刷题笔试宝典,这里涵盖了市面上大部分的笔试题合集,希望助大家春秋招一臂之力