跳到内容
当前位置:首页>笔试真题>小红书笔试,难度较大(0325秋招笔试真题解析)

小红书笔试,难度较大(0325秋招笔试真题解析)

  • 2026-10-25 14:25:36
小红书笔试,难度较大(0325秋招笔试真题解析)

关注我们,每天更新大厂最新笔试题解析

前言

文末给大家推荐一下我们的活动,针对校招笔面试全覆盖的全程真一对一的提高,参加活动前会给你安排一个全面的摸底,摸底后会针对你的情况进行分析和对于参加活动的介绍,然后你再决定是否参加!

在线做题链接:https://niumacode.com/

  • 第一题(乱序数据解析):巧妙利用数据类型的排他性强特征(小写字母开头判别名称、包含小数点定位经验值),在乱序输入流中精准拦截并分类字段,打包后直接以用户编号为关键字完成升序排序重组,是考察基本功的优质签到题。
  • 第二题(无限轮互评模拟):摒弃低效的步进模拟,将连续的同属性串压缩分块。通过奇偶索引交替,模拟“敌军累加”与“友军抵消”的连锁反应,最终以总长度扣除存活的“绝对安全区”长度,在  复杂度内降维算出被消耗的总量。
  • 第三题(双向字符置换):紧扣“字典序优先极小化前缀”的贪心本质,借助线段树(RMQ)高效查找到最靠前且收益最大的首轮交换位置以敲定跨度步长。随后在后半段合法区间内再次贪心锁定代价最小的副交换点,从而实现“连带双重置换”约束下的全局字典序最小。

第一题

在线做题链接:https://niumacode.com/

题意

小红书数据库中有用户编号、用户名称和用户经验三个字段,其中: 用户编号为 1 到 10^9 间的整数,且唯一; 用户名称为长度不超过 10 的非空字符串,且仅由小写字母构成; 用户经验为 1 到 10^9 间的浮点数。 现在,你已经获取到了 n 条用户数据,每一条用户数据由:用户编号、用户名称、用户经验三个部分组成,但顺序是混乱的。 请按照:用户编号从小到大排序并将排序后的用户数据按照:用户编号、用户名称、用户经验的顺序输出。

输入描述

输入一个整数 n (1≤n≤10^5),表示用户数据的数量。此后 n 行,第 i 行依次输入以下三个部分表示第 i 条用户数据(不保证某个部分一定在前,即部分间的顺序是乱序的;各部分之间用空格分隔): 一个整数 xi (1≤xi≤10^9),表示用户编号; 一个长度仅由小写字母构成的字符串 si (1≤length(si)≤10),表示用户名称; 一个小数位数为两位的浮点数 ci (0≤ci≤10^9),表示用户经验。

输出描述

一共 n 行,第 i 行依次输出用户编号第 i 小的用户编号、用户名称和用户经验,用空格分隔。

示例1:

输入:

3
xhs 12 106.70
0.00 abc 11
6 xhs 666.66

输出:

6 xhs 666.66
11 abc 0.00
12 xhs 106.70

思路与代码

由于每条数据的三个字段输入顺序是随机的,但它们各自具有严格的数据类型排他性:由小写字母构成的字符串必是“用户名称”,包含小数点的浮点型格式必是“用户经验”,剩下的纯数字构成的必定是“用户编号”。在读入时,利用字符串首字母范围和是否包含 . 这两个特征,精准拦截并分类各个字段,将它们打包存入列表后,直接以用户编号为关键字进行升序排序并输出即可。

import sys

def solve():
# 快速读取所有标准输入并按空白字符分割
    input_data = sys.stdin.read().split()
if not input_data:
return

    n = int(input_data[0])
    idx = 1

    user_list = []
for _ in range(n):
        user_id = 0
        user_name = ""
        user_exp = ""

# 每条记录由 3 个部分组成,乱序输入
for _ in range(3):
            token = input_data[idx]
            idx += 1

# 依靠特征区分当前字段 (token) 属于哪种数据
if'a' <= token[0] <= 'z':
                user_name = token        # 小写字母开头为用户名称
elif'.'in token:
                user_exp = token         # 包含小数点为经验值
else:
                user_id = int(token)     # 否则为用户编号

        user_list.append((user_id, user_name, user_exp))

# 按照用户编号 user_id (即元组的第 0 个元素) 从小到大排序
    user_list.sort(key=lambda user: user[0])

# 统一格式化输出
    out = [f"{user[0]} {user[1]} {user[2]}"for user in user_list]
print('\n'.join(out))

if __name__ == '__main__':
    solve()

第二题

在线做题链接:https://niumacode.com/

题意

现在有 n 条 Plog 在首页上排成一列,队尾在下侧,队头在上侧。用长度为 n 的 01 串 s=s1s2…sn 表示这条队列,其中: 若 si=1,则第 i 条 Plog 属于美食; 若 si=0,则第 i 条 Plog 属于旅行。 一共会进行无限轮互评操作,每一轮: 所有 Plog 的拥有者同时向队头(右侧)互评; 互评只会影响每条 Plog 右侧的第一个异属性 Plog,如果右侧没有异属性 Plog,则不会产生互评操作; 每轮所有互评动作并行计算,然后一次性将所有已经有评论的 Plog 移出,形成新队列再进入下一轮;同一条 Plog 在一轮可能收获多条评价。

显然,无限进行下去,终究会出现不再有互评发生的情况。求整个过程中共有多少条 Plog 收获评价。

输入描述

第一行输入一个整数 n (1≤n≤10^5),表示 Plog 数量。第二行输入一个长度为 n 且只由字符 0 和 1 构成的字符串 s,表示 Plog 的属性分布,其中 si 为从左向右第 i 条 Plog 的属性。

输出描述

输出一个整数,表示所有互评结束后共有多少条 Plog 收获评价。

示例1:

输入:

5
11101

输出:

2

解释: 在这个样例中:第一轮,第三条(1)评论第四条(0),第四条(0)评论第五条(1),共 2 条 Plog 收获评论;剩余前三条 Plog 拼接为 "111",此时剩下的全是美食 Plog,不再发生互评现象。

示例2:

输入:

10
1100010101

输出 8

解释:
"1100010101" → "1100" → "110" → "11"
一共有 8 条 Plog 被评论

思路与代码

首先将连续的同属性 Plog 压缩成若干个长度块,最左侧的第一个块视为“绝对安全区”,后续的块按照索引奇偶性交替扮演“异属性(敌人)”和“同属性(友军)”的角色。在从左到右遍历的过程中,将奇数索引的异属性长度不断累加,代表“挡在前面的敌人”;当遇到偶数索引的同属性块时,让它与前面累积的敌人互相消耗(同属性多则余下部分并入安全区,异属性多则同属性被全部吞噬)。最终,用 Plog 总长度减去存活在安全区的总长度,就是整个过程中发生过互评(被消耗掉)的 Plog 数量。

import sys

def solve():
# 快速读取所有标准输入并按空白字符分割
    input_data = sys.stdin.read().split()
if not input_data:
return

    n = int(input_data[0])
    s = input_data[1]

if n <= 1:
print(0)
return

# 将连续相同的字符压缩为长度块
    block_lengths = []
    current_char = s[0]
    current_count = 1

for i in range(1, n):
if s[i] == current_char:
            current_count += 1
else:
            block_lengths.append(current_count)
            current_char = s[i]
            current_count = 1
    block_lengths.append(current_count)

# 如果只有一种属性,没有互评
if len(block_lengths) <= 1:
print(0)
return

    safe_count = block_lengths[0]  # 第一块必定是安全的起始块
    pending_enemies = 0            # 累积的异属性数量(等待抵消的敌人)

for i in range(1, len(block_lengths)):
if i % 2 != 0:
# 奇数索引:异属性块,敌人数量增加
            pending_enemies += block_lengths[i]
else:
# 偶数索引:同属性块,与累积的敌人发生抵消
if block_lengths[i] > pending_enemies:
# 友军数量大于敌人,剩余友军加入安全区,敌人清空
                safe_count += block_lengths[i] - pending_enemies
                pending_enemies = 0
else:
# 友军数量小于等于敌人,友军全灭,敌人数量对应减少
                pending_enemies -= block_lengths[i]

# 总被评论数 = 总长度 - 最终存活的安全长度
    total_commented = n - safe_count
print(total_commented)

if __name__ == '__main__':
    solve()

第三题

在线做题链接:https://niumacode.com/

题意

为了提升小红书笔记标签的可读性,我们计划对标签字符串进行一次双向字符置换操作,以获得更小的字典序结果。具体地,给定一个长度为 n 的字符串 s(下标从 1 开始),你可以进行一次如下操作: 选取三个整数 (i,j,k),满足 1≤i≤j≤n,1≤i−k,j+k≤n 且 k>0;将 si 与 si−k 交换,并将 sj 与 sj+k 交换。 在所有可行操作中,找出能够使字符串字典序最小的结果,并输出该字符串。 【名词解释】 字典序比较:从字符串第一个字符开始逐个比较,直至出现不同位置,字符较小的一方字典序更小;若一个字符串是另一字符串的前缀,则较短字符串字典序更小。

输入描述

第一行输入一个正整数 n (1≤n≤2×10^5),表示字符串长度。 第二行输入一个由小写字母构成的字符串 s。

输出描述

输出一个字符串,表示经过至多一次操作后可获得的字典序最小字符串。

示例:

输入:

5
baced

输出:

abcde

说明: 在这个样例中,选择三元组 (2,4,1) 可得到结果 “abcde”。

**思路与代码

先尽量让字符串最靠前的位置变小,因为字典序比较先看前面; 设第一次交换把 s[pos1] 和右边距离为 len 的更小字符换过来,之后第二次交换也必须用同样的 len,那就在后半段里找一个影响最小的位置去交换即可。

import sys

def merge(a, b):
if a[0] < b[0]:
return a
if a[0] > b[0]:
return b
if a[1] >= b[1]:
return a
return b

def main():
    data = sys.stdin.buffer.read().split()
    n = int(data[0])
    s = data[1].decode()

if n < 4:
print(s)
return

    a = [ord(c) - 97 for c in s]

    size = 1
while size < n:
        size <<= 1

    inf = (30, -1)
    tr = [inf] * (size << 1)

for i in range(n):
        tr[size + i] = (a[i], i)

for i in range(size - 1, 0, -1):
        tr[i] = merge(tr[i << 1], tr[i << 1 | 1])

    def query(left, right):
        left += size
        right += size
        res_left = inf
        res_right = inf
while left <= right:
if left & 1:
                res_left = merge(res_left, tr[left])
                left += 1
if not (right & 1):
                res_right = merge(tr[right], res_right)
                right -= 1
            left >>= 1
            right >>= 1
return merge(res_left, res_right)

    pos1 = -1
    pos2 = -1

for i in range(n):
        lim = (n - i - 2) >> 1
if lim <= 0:
continue
        left = i + 1
        right = i + lim
        c, pos = query(left, right)
if c < a[i]:
            pos1 = i
            pos2 = pos
break

if pos1 == -1:
print(s)
return

    length = pos2 - pos1
    left = pos2 + 1
    right = n - length - 1

    pos3 = -1
    ok = False

for i in range(left, right + 1):
if a[i + length] < a[i]:
            pos3 = i
            ok = True
break

if not ok:
for i in range(left, right + 1):
if a[i + length] == a[i]:
                pos3 = i
                ok = True
break

if not ok:
        pos3 = right

    res = list(s)
    res[pos1], res[pos2] = res[pos2], res[pos1]
    res[pos3], res[pos3 + length] = res[pos3 + length], res[pos3]

print(''.join(res))

main()
最后插一下我们的进阶一对一辅导啦 
我们是一个针对技术岗(前后端开发、测试、测开、大数据开发、大模型、ai等相关岗位)校招一对一进阶提高的工作室。我们从2020年2月份开始,迄今整整六年的时间,带领900+学员斩获4000+中大厂offer,参加活动的同学人均5个中大厂offer以上,以下是我们活动内容的介绍!
万诺coding

我们主要是针对有一定基础的同学提供全程一对一笔试、面试辅导,针对每个同学不同的情况定制内容,包括但不限于“笔试及面试算法”/“基础八股/“项目及实习梳理”/“面试技巧”/“面试复盘”等内容。

摸底测试:如果有兴趣深入了解我们的活动,需要先参加我们的“摸底测试”(类似面试),方便我们了解你的具体情况(主要是code能力和计算机素养),定制出相应的辅导计划。摸底测试后,我们会定制化一个针对性的提高计划。然后你再考虑是否参加我们的活动。 

承诺保offer:通过摸底测试后,我们会针对每个同学的情况给定一个“保offer”计划。然后同学可以根据自己的实际情况考虑参不参加我们的活动。

有兴趣的同学可以扫码添加我们的微信(whynotlab) 

微信咨询 微信客服二维码微信扫一扫 · 添加人工客服 QQ QQ咨询 QQ咨询二维码QQ扫一扫 · 添加人工客服 帮助手册