小红书笔试 小红书笔试题 小红书 2026春招笔试真题解析

笔试时间:2026年3月18日

往年笔试合集:

2023春招秋招笔试合集

2024春招秋招笔试合集

第一题:冲突约束

题目

小红书生态团队在评论审核中,需要对得分接近的评论判定观点相近,这一判断逻辑可以帮助团队灵活的调整评论区的观点统一性/观点多样性。

现在,将模型简化如下:给定长度为 n 的整数数组 a 和一个整数 k。若 |a[i] - a[j]| ≤ k,则称 a[i] 与 a[j] 观点相近。

一次操作可以选择一对元素,并将其同时从数组中删除(数组长度减少 2)。

经过若干操作后,需要保证数组中不含任何观点相近的元素,且希望保留的元素数量尽可能多。

请你计算,经过若干操作后,最终保留下来的最大元素数量。

输入描述

每个测试文件均包含多组测试数据。第一行输入一个整数 T (T ≥ 1) 代表数据组数,每组测试数据描述如下:

第一行输入两个整数 n 和 k (1 ≤ n ≤ 2×10⁵),表示数组长度、观点相近的阈值。

第二行输入 n 个整数 a[i] (|a[i]| ≤ 10⁹),表示数组元素。

除此之外,保证单个测试文件的 n 之和不超过 2×10⁵。

输出描述

对于每组测试数据,新起一行输出一个整数,表示最终保留下来的最大元素数量。

样例输入

2
5 2
1 2 4 7 9
4 0
1 1 2 5

样例输出

3
2

样例解释

对于第一组测试数据,保留 {1, 4, 7},我们可以证明这是最优的。

对于第二组测试数据,在 k=0 时,相等元素冲突,保留 {1, 5},我们可以证明这是最优的。

参考题解

解题思路:

利用贪心算法来寻找满足不冲突条件下的"最大独立集"。首先对整个数组进行升序排序,然后从左到右依次遍历,只要当前遍历到的元素与上一个决定保留的元素差值严格大于阈值 k(即两者不冲突),就贪心地将其加入保留集合。这种从左到右取最小可行值的策略,能保证在有限的数值范围内塞下尽可能多的不冲突元素,从而求出理论上最多能保留的个数。

其次,需要处理题目中"每次必须同时删除一对(两个)元素"的限制。这意味着最终被剔除的元素总数必须是偶数。因此,在贪心求出最多保留个数后,计算被淘汰的元素数量(数组总长度减去最多保留个数)。如果这个淘汰数量是奇数,说明剩余的元素无法完美两两组队删除,必须从保留的集合中再多牺牲掉一个元素,让被删除总数变成偶数。

C++:

#include <bits/stdc++.h>
using namespace std;

int main() {
    int T;
    scanf("%d", &T);
    while (T--) {
        int n, k;
        scanf("%d%d", &n, &k);
        vector<int> a(n);
        for (int i = 0; i < n; i++) {
            scanf("%d", &a[i]);
        }
        sort(a.begin(), a.end());

        int validCount = 0;
        long long prev = -3000000000LL;
        for (int i = 0; i < n; i++) {
            if (a[i] - prev > k) {
                validCount++;
                prev = a[i];
            }
        }

        if ((n - validCount) % 2 == 1) {
            validCount--;
        }
        printf("%d\n", validCount);
    }
    return 0;
}

Java:

import java.util.Arrays;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner reader = new Scanner(System.in);
        if (reader.hasNextInt()) {
            int testCases = reader.nextInt();
            for (int t = 0; t < testCases; t++) {
                int size = reader.nextInt();
                int limit = reader.nextInt();
                int[] elements = new int[size];
                for (int idx = 0; idx < size; ++idx) {
                    elements[idx] = reader.nextInt();
                }
                Arrays.sort(elements);

                int validCount = 0;
                long previousVal = -3000000000L;
                for (int idx = 0; idx < size; ++idx) {
                    if (elements[idx] - previousVal > limit) {
                        validCount++;
                        previousVal = elements[idx];
                    }
                }

                if ((size - validCount) % 2 == 1) {
                    validCount--;
                }
                System.out.println(validCount);
            }
        }
        reader.close();
    }
}

Python:

import sys
input = sys.stdin.readline

T = int(input())
for _ in range(T):
    n, k = map(int, input().split())
    a = list(map(int, input().split()))
    a.sort()

    valid_count = 0
    prev = -3000000000
    for x in a:
        if x - prev > k:
            valid_count += 1
            prev = x

    if (n - valid_count) % 2 == 1:
        valid_count -= 1
    print(valid_count)

第二题:小红书丝带AR特效

题目

在小红书"品牌创意工坊"中,营销人员可以为直播和短视频活动创建定制化丝带AR特效,结合品牌ID与礼盒包装场景,实现动态丝带动画。为了支撑亿级日活的前端渲染,后端需要在活动发布时预先计算并缓存所有可能的切割方案数,确保小程序组件和Web端秒级响应。

现有一根虚拟丝带长度为 n,可以将其分割成若干段或保持一整段不动,但是每段长度只能取整数 x、y 或 z 中的一个,且不允许任何长度为 x 的段后面直接跟随长度为 z 的段。

请对所有长度 i (1 ≤ i ≤ n),统计合法的切割方案数,供小红书前端组件批量加载与渲染。由于答案可能很大,请将答案对 10⁹+7 取模后输出。顺序不同视为不同方案。

输入描述

每个测试文件均包含多组测试数据。第一行输入一个整数 T (T ≥ 1) 代表数据组数,每组测试数据描述如下:

在一行上输入四个整数 n, x, y, z (1 ≤ n ≤ 10⁶),代表最大丝带长度、可选分段长度 x, y, z。保证 x, y, z 两两互不相等。

除此之外,保证单个测试文件的 n 之和不超过 10⁶。

输出描述

对于每组测试数据,新起一行,输出 n 个整数,其中第 i 个数表示长度为 i 的丝带的合法分割方案数对 10⁹+7 取模的结果。

样例输入

2
5 1 2 3
4 1 2 3

样例输出

1 2 4 6 11
1 2 4 6

样例解释

在第一个样例中,当 n=5 时:

  • i=1 时,仅有一种分割方案 {1};
  • i=2 时,有 {1,1} 和 {2} 两种方案;
  • i=3 时,有 {1,1,1}, {1,2}, {2,1}, {3} 共 4 种方案;
  • i=4 时,按不带约束的方式共有 7 种方案,但其中 {1,3} 不合法,故为 6 种;
  • i=5 时,合法方案共 11 种。

参考题解

解题思路:

采用动态规划。使用一个主数组 dpSum 记录到达每一个指定长度时的总合法方案数;同时,为了处理题目中"长度 x 后面不能直接跟 z"的特殊约束,额外使用一个辅助数组 stateX 来专门记录"以长度为 x 的段作为结尾"的方案数。

在状态转移过程中,对于任意长度 i,其合法方案数由最后一步的三种切割选择累加而成:如果最后切的是 x 或 y,其方案数分别直接继承自长度为 i-x 和 i-y 时的总方案数;如果最后切的是 z,则必须从长度为 i-z 的总方案数中,减去那些以 x 结尾的方案(即 stateX[i-z]),从而精准剔除掉"x 后面接 z"的不合法组合。最后将这三个分支的有效方案数相加并进行取模,即可递推得到答案。

C++:

#include <bits/stdc++.h>
using namespace std;

const int MODULO = 1000000007;

int main() {
    int t;
    scanf("%d", &t);
    const int LIMIT = 1000005;
    vector<int> stateX(LIMIT, 0);
    vector<int> dpSum(LIMIT, 0);

    while (t--) {
        int len, x, y, z;
        scanf("%d%d%d%d", &len, &x, &y, &z);

        dpSum[0] = 1;
        stateX[0] = 0;

        for (int i = 1; i <= len; i++) {
            int pickX = (i >= x) ? dpSum[i - x] : 0;
            int pickY = (i >= y) ? dpSum[i - y] : 0;
            int pickZ = 0;
            if (i >= z) {
                pickZ = dpSum[i - z] - stateX[i - z];
                if (pickZ < 0) pickZ += MODULO;
            }

            stateX[i] = pickX;
            long long currentTotal = (long long)pickX + pickY + pickZ;
            dpSum[i] = (int)(currentTotal % MODULO);

            printf("%d", dpSum[i]);
            if (i < len) printf(" ");
        }
        printf("\n");
    }
    return 0;
}

Java:

import java.util.Scanner;

public class Main {
    static final int MODULO = 1000000007;

    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        if (!input.hasNextInt()) {
            return;
        }
        int t = input.nextInt();
        int limit = 1000005;
        int[] stateX = new int[limit];
        int[] dpSum = new int[limit];

        for (int k = 0; k < t; k++) {
            int len = input.nextInt();
            int x = input.nextInt();
            int y = input.nextInt();
            int z = input.nextInt();

            dpSum[0] = 1;
            stateX[0] = 0;

            for (int idx = 1; idx <= len; idx++) {

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

2025 春招笔试合集 文章被收录于专栏

2025打怪升级记录,大厂笔试合集 C++, Java, Python等多种语言做法集合指南

全部评论

相关推荐

当AI能干活了,我们还能干什么?这个问题我最近一直在想。AI确实能写代码、画图、写文案、剪视频了,而且速度比人快、成本比人低。但仔细想想,AI做的都是“执行层”的事——你给我指令,我产出结果。真正值钱的,从来不是执行本身。**我觉得能站稳脚跟的,是这三类人:**---**1.&nbsp;提需求的人**AI再强,也需要有人告诉它“做什么”。产品经理、业务架构师、项目经理——这些定义问题、拆解目标、做决策的角色,AI暂时替代不了。因为需求来自对业务的理解、对人性的洞察,这些AI没有。**2.&nbsp;判断好坏的人**AI能生成十个方案,但哪个能用?哪个符合品牌调性?哪个有法律风险?——这些判断需要行业经验、审美、责任感。资深设计师、技术负责人、风控专家,做的不是“干活”,是“把关”。**3.&nbsp;建立信任的人**客户不会因为“AI写的方案”就签合同,他们信的是人——信任你的专业、你的靠谱、你关键时刻能兜底。销售、咨询、客户成功,这些靠关系和人品的岗位,AI很难替代。---**所以我的答案是:**未来不是“人被AI替代”,而是“只会执行的人被会用AI的人替代”。能用AI放大自己能力的人,反而更值钱。写代码的不如做架构的,画图的不如定风格的,剪视频的不如懂叙事的——AI是杠杆,但支点还是人。你觉得自己属于哪一类?
AI时代,哪个岗位还有“...
点赞 评论 收藏
分享
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

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