【笔试刷题】虾皮-2026.03.08-改编真题
✅ 春招备战指南 ✅
💡 学习建议:
- 先尝试独立解题
- 对照解析查漏补缺
🧸 题面描述背景等均已深度改编,做法和题目本质基本保持一致。
🍹 感谢各位朋友们的订阅,你们的支持是我们创作的最大动力
🌸 目前本专栏已经上线200+套真题改编解析,后续会持续更新的
春秋招笔试机考招合集 -> 互联网必备刷题宝典🔗
虾皮-2026.03.08
这套题整体很典型:第一题是排序加双指针的标准计数题,第二题考的是字符串中心扩展,第三题则回到最基础的二叉树层序遍历。难度分层比较清晰,前两题更看重是否能迅速抓住经典模型,第三题偏热身。
题目一:三角形组合数量
这题表面是在数三元组,真正关键是把“三角形条件”转成排序后的单调性。固定最长边以后,双指针可以一次性统计整段合法区间,不需要一个个三元组去试。
难度:中等
题目二:找出最长回文字串
题面已经把范围收窄到“只考虑奇数长度回文”,所以直接枚举中心往两边扩展就够了。容易忽略的是同长度时要返回第一个,这意味着更新答案时只能在“更长”时替换。
难度:中等
题目三:二叉树遍历
这题本质就是层序遍历,难点主要在输入还原:要先把带 # 的层序序列建成树,再做标准 BFS。实现上只要把“当前层节点数”先记下来,按层输出就很自然了。
难度:简单
01. 三角展架方案统计
问题描述
小兰正在布置一个展厅。仓库里有 根轻型支架,每根支架都有一个长度值。现在她想从中选出 3 根支架,拼成一个稳定的三角展架。
只有当任意两根支架的长度和都大于第三根时,这 3 根支架才能组成三角形。请统计一共有多少种不同的选法。
输入格式
一行,输入一个整数 和一个长度数组,格式如
4,[1,1,1,1]。
输出格式
输出一个整数,表示可以组成三角形的三元组数量。
样例输入
4,[1,1,1,1]
样例输出
4
数据范围
| 样例 | 解释说明 |
|---|---|
| 样例1 | 4 根支架长度都为 1,任取 3 根都满足三角形条件,所以答案是 |
题解
这道题最朴素的想法是枚举所有三元组,但这样需要 ,当
达到
时肯定过不去。
更合适的做法是先排序。排完序以后,如果固定某个位置 作为最长边,那么只要另外两条边满足
就能组成三角形。因为数组有序,所以一旦某个 i 与 j 满足条件,那么区间 i..j-1 中的所有位置都和 j 一起满足条件,可以一次性把这些方案全部加进答案里。
具体步骤如下:
- 将数组升序排序。
- 从右到左枚举最长边位置
。
- 设两个指针
i=0、j=k-1。 - 如果
,说明
i..j-1这些左端点都合法,此时答案加上j-i,再把j左移。 - 否则说明当前最短边太短,需要把
i右移。
每个 的双指针扫描都是线性的,所以总复杂度是
,能够满足题目要求。
参考代码
- Python
import sys
import re
input = lambda: sys.stdin.readline().strip()
def solve():
line = input()
# 提取整行中的所有整数,兼容 `n,[...]` 这种输入格式。
nums = list(map(int, re.findall(r'-?\d+', line)))
if not nums:
print(0)
return
# 优先按题图中的格式处理:第一个数是 n,后面是数组元素。
if len(nums) >= 2 and nums[0] == len(nums) - 1:
arr = nums[1:]
else:
arr = nums
# 排序后才能使用双指针批量计数。
arr.sort()
n = len(arr)
ans = 0
# 枚举最长边的位置。
for k in range(n - 1, 1, -1):
i, j = 0, k - 1
while i < j:
# 当前最短边和次长边已经能超过最长边。
if arr[i] + arr[j] > arr[k]:
# 那么 i..j-1 都能与 j 组成合法三角形。
ans += j - i
j -= 1
else:
# 最短边太短,需要增大它。
i += 1
print(ans)
if __name__ == "__main__":
solve()
- Cpp
#include <bits/stdc++.h>
using namespace std;
vector<int> parse_nums(const string& line) {
vector<int> nums;
int i = 0, n = (int)line.size();
while (i < n) {
if (isdigit(line[i]) || line[i] == '-') {
int j = i;
if (line[i] == '-') {
i++;
}
while (i < n && isdigit(line[i])) {
i++;
}
nums.push_back(stoi(line.substr(j, i - j)));
} else {
i++;
}
}
return nums;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
string line;
getline(cin, line);
// 解析输入中的所有整数。
vector<int> nums = parse_nums(line);
if (nums.empty()) {
cout << 0 << '\n';
return 0;
}
vector<int> arr;
if ((int)nums.size() >= 2 && nums[0] == (int)nums.size() - 1) {
// 题图中的格式:第一个数是 n,后面是数组内容。
arr.assign(nums.begin() + 1, nums.end());
} else {
arr = nums;
}
sort(arr.begin(), arr.end());
long long ans = 0;
int n = (int)arr.size();
// 从右到左枚举最长边。
for (int k = n - 1; k >= 2; --k) {
int i = 0, j = k - 1;
while (i < j) {
if (arr[i] + arr[j] > arr[k]) {
// 固定 j 时,i..j-1 都合法。
ans += j - i;
--j;
} else {
++i;
}
}
}
cout << ans << '\n';
return 0;
}
- Java
import java.io.*;
import java.util.*;
public class Main {
private static List<Integer> parseNums(String line) {
List<Integer> nums = new ArrayList<>();
int i = 0, n = line.length();
while (i < n) {
char ch = line.charAt(i);
if (Character.isDigit(ch) || ch == '-') {
int j = i;
if (ch == '-') {
i++;
}
while (i < n && Character.isDigit(line.charAt(i))) {
i++;
}
nums.add(Integer.parseInt(line.substring(j, i)));
} else {
i++;
}
}
return nums;
}
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = br.readLine();
List<Integer> nums = parseNums(line);
if (nums.isEmpty()) {
System.out.println(0);
return;
}
List<Integer> arr = new ArrayList<>();
if (nums.size() >= 2 && nums.get(0) == nums.size() - 1) {
// 按 `n,[...]` 的输入方式取出真实数组。
for (int i = 1; i < nums.size(); i++) {
arr.add(nums.get(i));
}
} else {
arr.addAll(nums);
}
Collections.sort(arr);
long ans = 0;
int n = arr.size();
// 枚举最长边。
for (int k = n - 1; k >= 2; k--) {
int i = 0, j = k - 1;
while (i < j) {
if (arr.get(i) + arr.get(j) > arr.get(k)) {
// 对当前 j,区间 i..j-1 都能组成三角形。
ans += j - i;
j--;
} else {
i++;
}
}
}
System.out.println(ans);
}
}
02. 灯带最美对称段
问题描述
小兰正在设计一条互动灯带。灯带会显示一串字符,她想从中截出一段“最对称”的内容,作为开场动画的核心片段。
如果一个字符串正着读和反着读完全一样,就把它看作回文字串。现在给定一个字符串 ,请找出其中最长的奇数长度回文字串;如果有多个长度相同的答案,返回最先出现的那个。
输入格式
一行,一个字符串,格式如 "babad"。
输出格式
输出满足要求的最长奇数长度回文字串,格式与样例一致。
样例输入
"babad"
样例输出
"bab"
数据范围
-
题图没有展示明确范围。为了便于本地 OJ 落地,这里补充为:
。
-
字符串仅包含英文字母。
| 样例 | 解释说明 |
|---|---|
| 样例1 | "bab" 和 "aba" 都是长度为 3 的奇数回文,但题目要求有多个答案时返回第一个,所以输出 "bab"。 |
题解
因为题目明确要求“回文字串的长度是奇数”,所以没有必要去处理偶数长度中心,只需要枚举每个字符作为中心即可。
设当前中心在位置 。从这个位置开始,令两个指针同时向左右扩展:
- 左指针从
往左走。
- 右指针从
往右走。
- 只要两边字符相同,就说明当前区间仍然是回文。
这样就能枚举出所有以 为中心的奇数长度回文。对每个中心都做一次扩展,记录最长答案即可。
有一个小细节:如果遇到多个相同长度的答案,题目要求返回第一个。处理起来很简单——只有在“更长”时才更新答案,长度相同就保持原结果不变。因为枚举中心是从左到右进行的,所以最先记录下来的自然就是更靠前的答案。
时间复杂度是 ,因为每个中心最坏都会向两边扩展到整串长度。空间复杂度是
。
参考代码
- Python
import sys
input = lambda: sys.stdin.readline().strip()
def strip_quote(s):
# 兼容样例中的双引号写法,也兼容直接输入原字符串。
if len(s) >= 2 and s[0] == s[-1] and s[0] in "\"'":
return s[1:-1]
return s
def solve():
s = strip_quote(input())
n = len(s)
if n == 0:
print('""')
return
# 初始答案至少包含一个字符。
best_l = 0
best_len = 1
# 每个位置都作为奇数长度回文的中心。
for c in range(n):
l = r = c
while l >= 0 and r < n and s[l] == s[r]:
cur_len = r - l + 1
# 只有更长时才更新,保证相同长度保留第一个。
if cur_len > best_len:
best_len = cur_len
best_l = l
l -= 1
r += 1
ans = s[best_l:best_l + best_len]
print('"' + ans + '"')
if __name__ == "__main__":
solve()
- Cpp
#include <bits/stdc++.h>
using namespace std;
string strip_quote(string s) {
if (s.size() >= 2 && s.front() == s.back() &&
(s.front() == '"' || s.front() == '\'')) {
return s.substr(1, s.size()
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
互联网刷题笔试宝典,这里涵盖了市面上大部分的笔试题合集,希望助大家春秋招一臂之力