【笔试刷题】虾皮-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} 可以生成 ab{c,{d,e}} 可以生成 cde,两边直接相邻表示拼接,所以最后得到 acadaebcbdbe
补充示例 若输入为 {{a,z},a{b,c},{ab,z}},去重并排序后得到 aabacz,因此输出先写 4,再按顺序逐行输出这 4 个单词。

题解

这题的难点不在集合操作本身,而在于先把表达式按正确的优先级解析出来。

可以把语法拆成 3 层:

  • expr:处理并集,也就是逗号分隔的部分。
  • term:处理连续拼接。
  • factor:处理一个最小单元,要么是一段连续字母,要么是一对花括号包起来的子表达式。

优先级关系是:

  • 花括号里的内容先算;
  • 直接相邻的拼接高于逗号并集;
  • 逗号最后再做并集。

于是可以直接写一个递归下降解析器。

1. factor

如果当前位置是 {,那就递归解析里面的完整表达式,直到读到匹配的 }

如果当前位置是字母,就把这一段连续的小写字母整体读出来,作为只含一个单词的集合返回。

2. term

term 负责连续拼接。假设当前已经有一个集合 A,后面又解析出了一个集合 B,那么新的结果就是它们的笛卡尔积拼接:

为了让第一个因子也能统一处理,可以把初始值设成只含空串的集合 {""}

3. expr

expr 负责并集。先解析一个 term,之后只要遇到逗号,就继续解析下一个 term,再把两个集合合并起来即可。

因为题目本身要求去重,集合结构天然就能帮忙消掉重复答案。最后再把结果按字典序输

剩余60%内容,订阅专栏后可继续查看/也可单篇购买

互联网刷题笔试宝典 文章被收录于专栏

互联网刷题笔试宝典,这里涵盖了市面上大部分的笔试题合集,希望助大家春秋招一臂之力

全部评论

相关推荐

牛客52811839...:实习要写出来业务和产出,你这写的像流水账没人看。项目经历也没有,换个极简简历试试
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务