【笔试刷题】虾皮-2026.03.23-改编真题
✅ 春招备战指南 ✅
💡 学习建议:
- 先尝试独立解题
- 对照解析查漏补缺
🧸 题面描述背景等均已深度改编,做法和题目本质基本保持一致。
🍹 感谢各位朋友们的订阅,你们的支持是我们创作的最大动力
🌸 目前本专栏已经上线200+套真题改编解析,后续会持续更新的
春秋招笔试机考招合集 -> 互联网必备刷题宝典🔗
虾皮-2026.03.23
虾皮-2026.03.23
这套题的梯度很清楚。第 1 题是一次扫描的经典贪心,重点在于把“历史最低买价”维护对;第 2 题是整套里最重的一题,要把表达式按优先级解析出来,再做集合拼接与并集;第 3 题则很轻,抓住“空格数 + 1”这个观察就能秒掉。
题目一:报价窗口里的最大收益
每天都尝试把当天当成卖出日,同时维护之前最便宜的买入价,就能在线性时间里拿到最优答案。
难度:Low
题目二:标签模板的有序展开
关键不是暴力拼字符串,而是先把表达式语法拆成“并集、拼接、最小因子”三层,再用递归下降稳定地展开集合。
难度:High
题目三:消息列表里的最长一句
题目保证每个句子格式规整,所以一句话的单词数直接等于空格数加一,逐句取最大值即可。
难度:Low
1. 报价窗口里的最大收益
问题描述
小基 在整理一款商品最近 天的报价记录。第
天的价格记为
。
她只允许做一笔交易:
- 选择某一天买入;
- 再选择未来某一天卖出;
- 买入日和卖出日必须不同。
请你计算这笔交易最多能获得多少收益。如果始终无法赚到钱,就输出 0。
输入格式
第一行输入一个整数 ,表示报价记录的天数。
第二行输入 个整数
,表示每天的报价。
输出格式
输出一个整数,表示最多能够获得的收益。
样例输入
6
7 1 5 3 6 4
样例输出
5
数据范围
| 样例 | 解释说明 |
|---|---|
| 样例1 | 在价格为 1 的那天买入,在价格为 6 的那天卖出,收益是 5。 |
| 补充示例 | 若报价是 7 6 4 3 1,价格一直下降,无论怎么选都不能盈利,所以答案是 0。 |
题解
这题只允许买一次、卖一次,所以真正要找的是:
某一天卖出时,前面有没有更便宜的买入机会。
于是可以从左到右扫一遍数组,同时维护两个量:
low:当前为止见过的最低价格,也就是最合适的买入价。ans:当前为止能够得到的最大收益。
扫描到当天价格 时,只有两种情况:
- 如果
比
low还小,那它更适合作为新的买入价,直接更新low。 - 否则就尝试把今天当成卖出日,候选收益是
,再拿它更新答案。
为什么这样就够了?
- 对于任意一个卖出日,最优买入日一定是它之前价格最低的那一天。
low恰好一直维护着这个信息。- 所以每一天都只需要和历史最低价配对一次,不用回头重试。
整趟扫描只会遍历数组一次,时间复杂度是 ,额外空间复杂度是
。
参考代码
- Python
import sys
input = lambda:sys.stdin.readline().strip()
def solve():
n = int(input())
arr = list(map(int, input().split()))
# low 维护历史最低买入价,ans 维护当前最大收益。
low = arr[0]
ans = 0
for i in range(1, n):
x = arr[i]
# 如果今天更便宜,就把它记成新的买入候选日。
if x < low:
low = x
else:
# 否则尝试把今天当卖出日,刷新最大收益。
ans = max(ans, x - low)
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<int> arr(n);
for (int i = 0; i < n; i++) {
cin >> arr[i];
}
// low 表示扫到当前位置前的最低价格。
int low = arr[0];
int ans = 0;
for (int i = 1; i < n; i++) {
int x = arr[i];
// 今天价格更低时,直接刷新买入价。
if (x < low) {
low = x;
} else {
// 否则把今天当卖出日,尝试更新答案。
ans = max(ans, x - low);
}
}
cout << ans << '\n';
return 0;
}
- Java
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
FastScanner fs = new FastScanner(System.in);
int n = fs.nextInt();
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = fs.nextInt();
}
// low 记录历史最低价格,ans 记录最大收益。
int low = arr[0];
int ans = 0;
for (int i = 1; i < n; i++) {
int x = arr[i];
// 更低的价格更适合作为新的买入点。
if (x < low) {
low = x;
} else {
// 今天卖出的收益由“当前价 - 历史最低价”得到。
ans = Math.max(ans, x - low);
}
}
System.out.println(ans);
}
static class FastScanner {
private final InputStream in;
private final byte[] buf = new byte[1 << 16];
private int len = 0;
private int ptr = 0;
FastScanner(InputStream is) {
in = is;
}
private int read() throws IOException {
if (ptr >= len) {
len = in.read(buf);
ptr = 0;
if (len <= 0) {
return -1;
}
}
return buf[ptr++];
}
int nextInt() throws IOException {
int c;
while ((c = read()) <= ' ') {
if (c == -1) {
return -1;
}
}
int sign = 1;
if (c == '-') {
sign = -1;
c = read();
}
int val = 0;
while (c > ' ') {
val = val * 10 + c - '0';
c = read();
}
return val * sign;
}
}
}
2. 标签模板的有序展开
问题描述
小兰在维护一套标签模板语言。一个表达式 expression 只会由小写字母、花括号和逗号组成,并且满足下面的规则:
- 如果给出一个单词,那么它表示一个只包含这个单词的集合。
- 如果给出两个表达式
和
,并把它们直接写在一起,那么结果表示把
中的每个单词和
中的每个单词依次拼接得到的新集合。
- 如果给出一个形如
{e_1,e_2,\ldots}的表达式,那么它表示这些表达式结果的并集。
现在给出一个合法表达式 expression。请你求出它最终能够生成的所有不同单词,并按字典序输出。
输入格式
输入一行字符串 expression,表示待展开的模板表达式。
输出格式
第一行输出一个整数 ,表示去重后得到的单词数量。
接下来输出 行,每行一个单词,要求按字典序从小到大排列。
样例输入
{a,b}{c,{d,e}}
样例输出
6
ac
ad
ae
bc
bd
be
数据范围
expression只包含{、}、,和小写英文字母- 题目保证输入表达式合法
| 样例 | 解释说明 |
|---|---|
| 样例1 | {a,b} 可以生成 a、b,{c,{d,e}} 可以生成 c、d、e,两边直接相邻表示拼接,所以最后得到 ac、ad、ae、bc、bd、be。 |
| 补充示例 | 若输入为 {{a,z},a{b,c},{ab,z}},去重并排序后得到 a、ab、ac、z,因此输出先写 4,再按顺序逐行输出这 4 个单词。 |
题解
这题的难点不在集合操作本身,而在于先把表达式按正确的优先级解析出来。
可以把语法拆成 3 层:
expr:处理并集,也就是逗号分隔的部分。term:处理连续拼接。factor:处理一个最小单元,要么是一段连续字母,要么是一对花括号包起来的子表达式。
优先级关系是:
- 花括号里的内容先算;
- 直接相邻的拼接高于逗号并集;
- 逗号最后再做并集。
于是可以直接写一个递归下降解析器。
1. factor
如果当前位置是 {,那就递归解析里面的完整表达式,直到读到匹配的 }。
如果当前位置是字母,就把这一段连续的小写字母整体读出来,作为只含一个单词的集合返回。
2. term
term 负责连续拼接。假设当前已经有一个集合 A,后面又解析出了一个集合 B,那么新的结果就是它们的笛卡尔积拼接:
为了让第一个因子也能统一处理,可以把初始值设成只含空串的集合 {""}。
3. expr
expr 负责并集。先解析一个 term,之后只要遇到逗号,就继续解析下一个 term,再把两个集合合并起来即可。
因为题目本身要求去重,集合结构天然就能帮忙消掉重复答案。最后再把结果按字典序输
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
互联网刷题笔试宝典,这里涵盖了市面上大部分的笔试题合集,希望助大家春秋招一臂之力