小红书笔试 小红书笔试题 20260308
笔试时间:2026年03月08日
往年笔试合集:
第一题:完美数字
难度:偏易
涉及知识点: 预处理与哈希集合(空间换时间)
题目描述
用户的每一次点赞都代表着对内容的喜爱。小红定义一个正整数 x 为完美数字,当且仅当同时满足以下两个条件:
- 可以将 x 写作一个公差为 1 且所有元素都是正整数的等差数列的乘积,例如,24 可以写作 2×3×4;
- 上述等差数列的长度至少为 3。
现在小红薯接收到多次 Plog 点赞数查询,每次给出一个正整数 x,请帮助小红薯判断该点赞数是否为完美数字。
输入描述
每个测试文件均包含多组测试数据。第一行输入一个整数 T(1 ≤ T ≤ 10^5)代表数据组数,每组测试数据描述如下:在一行上输入一个整数 x(1 ≤ x ≤ 10^9),表示一次点赞数查询。
输出描述
对于每组测试数据,新起一行,如果点赞数是完美数字,输出 YES;否则,输出 NO。
样例
输入:
3 6 2 24
输出:
YES NO YES
参考题解
解题思路:
题目要求的"完美数字"是至少3个连续正整数的乘积,且题目给定的最大查询值是 10^9。由于 1000 × 1001 × 1002 的结果已经大于 10^9,这意味着构成完美数字的连续序列的起始值最大也不会超过 1000。
基于这个边界条件,代码在正式读取输入前,先通过两层循环穷举了所有可能的起始值(1到1000)和后续的连续乘积,将所有小于等于 10^9 的"完美数字"提前计算出来并存入哈希集合(HashSet)中。这样在后续处理成千上万次查询时,只需要极快地判断该数字是否存在于集合中即可,有效避免了每次查询都重新计算而导致的超时问题。
Java:
import java.util.HashSet;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
HashSet<Integer> set = new HashSet<>();
for (long i = 1; i <= 1000; i++) {
long p = i * (i + 1);
for (long j = i + 2; ; j++) {
p *= j;
if (p > 1000000000L) {
break;
}
set.add((int) p);
}
}
Scanner sc = new Scanner(System.in);
if (sc.hasNextInt()) {
int t = sc.nextInt();
while (t-- > 0) {
int x = sc.nextInt();
if (set.contains(x)) {
System.out.println("YES");
} else {
System.out.println("NO");
}
}
}
}
}
C++:
#include <iostream>
#include <unordered_set>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
unordered_set<int> st;
for (long long i = 1; i <= 1000; i++) {
long long p = i * (i + 1);
for (long long j = i + 2; ; j++) {
p *= j;
if (p > 1000000000LL) {
break;
}
st.insert((int)p);
}
}
int t;
cin >> t;
while (t--) {
int x;
cin >> x;
if (st.count(x)) {
cout << "YES\n";
} else {
cout << "NO\n";
}
}
return 0;
}
Python:
import sys
def main():
input_data = sys.stdin.buffer.read().split()
idx = 0
perfect = set()
for i in range(1, 1001):
p = i * (i + 1)
j = i + 2
while True:
p *= j
if p > 1000000000:
break
perfect.add(p)
j += 1
t = int(input_data[idx]); idx += 1
results = []
for _ in range(t):
x = int(input_data[idx]); idx += 1
results.append("YES" if x in perfect else "NO")
print("\n".join(results))
if __name__ == "__main__":
main()
第二题:强迫症
难度:中等
涉及知识点: 双指针与贪心,特征转化
题目描述
在小红书 App 首页的两列 Plog 中,小红薯独爱第一列。她将第一列每条 Plog 的点赞状态从上到下用一个二进制字符串 s 表示,其中:
- 字符
1表示用户已点赞第 i 条 Plog; - 字符
0表示用户未点赞第 i 条 Plog。
小红薯定义一轮点赞行为如下:
- 选择索引对 (l, r);
- 从第 l 条 Plog 开始,到第 r 条 Plog 结束,进行一次重复点赞行为。这会使得原本未点赞的 Plog 变为已点赞,原本已点赞的 Plog 变为未点赞。
小红薯希望使得这一列 Plog 的点赞状态调整为一个回文串,即第一条和最后一条 Plog 的点赞状态相同,第二条和倒数第二条 Plog 的点赞状态相同,以此类推。请计算她最少需要进行的点赞行为轮数。
输入描述
每个测试文件均包含多组测试数据。第一行输入一个整数 T(1 ≤ T ≤ 10^5)代表数据组数,每组测试数据描述如下:第一行输入一个整数 n(1 ≤ n ≤ 2×10^5),表示 Plog 数量;第二行输入一个长度为 n、由字符 0 和 1 构成的字符串 s,表示点赞状态。
除此之外,保证单个测试文件的 n 之和不超过 2×10^5。
输出描述
对于每一组测试数据,新起一行,输出一个整数,代表使字符串 s 成为回文串所需的最少点赞行为轮数。
样例
输入:
2 2 01 3 010
输出:
1 0
参考题解
解题思路:
这段代码的核心思路是统计对称位置上连续不匹配的"字符块"数量。要使字符串变成回文串,前半部分和后半部分对应位置的字符(即索引 idx 和 len - 1 - idx)必须相同。代码通过遍历字符串的前半段,将其与后半段的对应位置进行比对,找出所有不相等的配对。因为题目允许我们一次性翻转任意连续区间的状态,所以对于连续出现的不匹配配对,我们完全可以通过一次区间翻转操作(比如只翻转前半段的这个连续区间)将它们同时修正。因此,最少需要的操作次数,实际上就等于"连续不匹配区块"的数量。
Java:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
String initialLine = reader.readLine();
if (initialLine == null) return;
int testCases = Integer.parseInt(initialLine.trim());
StringBuilder output = new StringBuilder();
while (testCases-- > 0) {
int len = Integer.parseInt(reader.readLine().trim());
String seq = reader.readLine().trim();
int res = 0;
boolean active = false;
for (int idx = 0; idx < len / 2; idx++) {
if (seq.charAt(idx) != seq.charAt(len - 1 - idx)) {
if (!active) {
res++;
active = true;
}
} else {
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
2025打怪升级记录,大厂笔试合集 C++, Java, Python等多种语言做法集合指南

查看6道真题和解析