大厂真题

小红书通用岗 2026-09-10

本场考试概述

考试时间:2026年9月10日 考试岗位:通用岗 难度评级:中等

考点分析

  • 第一题:可达性 DP (bitset 优化)(难度中等)
  • 第二题:二分答案 + 贪心(难度中等)

建议策略

  • 第一题先把”两个值拆进两组”转成”给 数学公式(保留原始 SVG) 配正负号”,再按差值值域记录每格的可达集合,只保留最小差值会得到错误答案
  • 第二题看到”最小化最大值”就想二分答案,判定时贪心从左往右摆,注意两篇笔记可以紧挨着放,不需要留空位

第 1 题:平衡路径

题目描述

小红书的数据分析师正在处理一份 数学公式(保留原始 SVG)数学公式(保留原始 SVG) 列的实验数据表。每个单元格包含两个特征值,分别记为 数学公式(保留原始 SVG)数学公式(保留原始 SVG)

分析师需要从左上角的单元格 数学公式(保留原始 SVG) 开始,依次处理到右下角的单元格 数学公式(保留原始 SVG)。每次只能移动到正下方 数学公式(保留原始 SVG) 或正右方 数学公式(保留原始 SVG) 的相邻单元格,不能跳出表格。

对于每一个经过的单元格(包括起点和终点),分析师需要将它的两个特征值分别归入两个不同的数据组:将其中一个特征值归入”第一组”,另一个归入”第二组”。

也就是说,每个单元格的两个特征值会被拆开,一个进入第一组总和,一个进入第二组总和。

定义”组间差值”为:第一组总和与第二组总和之差的绝对值。

分析师希望通过选择合适的处理路径以及每个单元格的分配方式,使得最终的组间差值尽可能小。请你帮他计算出这个最小值。

输入描述

输入包含 数学公式(保留原始 SVG) 行。

第一行包含两个整数 数学公式(保留原始 SVG),表示表格的行数和列数。

接下来的 数学公式(保留原始 SVG) 行,每行包含 数学公式(保留原始 SVG) 个整数,其中第 数学公式(保留原始 SVG) 行第 数学公式(保留原始 SVG) 个数为 数学公式(保留原始 SVG)

再接下来的 数学公式(保留原始 SVG) 行,每行包含 数学公式(保留原始 SVG) 个整数,其中第 数学公式(保留原始 SVG) 行第 数学公式(保留原始 SVG) 个数为 数学公式(保留原始 SVG)

输出描述

输出一行一个整数,表示可能的最小组间差值。

样例1

输入

2 2
1 2
3 4
2 8
2 1

输出

1

题解:可达性 DP

思路分析

每个格子的两个值必须拆进两组,等价于给 数学公式(保留原始 SVG) 配一个正号或负号;要在所有从左上到右下的路径中,让路径上这些带号 数学公式(保留原始 SVG) 之和的绝对值最小。

这是一道把”求最小值”改写成”求可达集合”的网格 DP:只记每格的最小差值是错的,前半段差值为 数学公式(保留原始 SVG) 的方案后面遇到 数学公式(保留原始 SVG) 只能得到 数学公式(保留原始 SVG),而前半段差值为 数学公式(保留原始 SVG) 的方案反而能抵消成 数学公式(保留原始 SVG),所以必须保留每格能凑出的全部差值。

算法实现

先看集合有多大。路径恰好经过 数学公式(保留原始 SVG) 个格子,每个 数学公式(保留原始 SVG),差值一定落在 数学公式(保留原始 SVG) 内。枚举路径有 数学公式(保留原始 SVG) 条,指数级不可行;按差值值域做状态,每格只需一个长度 数学公式(保留原始 SVG) 的布尔数组 。

状态方程定义

数学公式(保留原始 SVG)

状态方程初始化

起点之前差值为 数学公式(保留原始 SVG),所以 数学公式(保留原始 SVG)

状态方程转移

数学公式(保留原始 SVG)

走到 数学公式(保留原始 SVG) 只能从上方或左方来,先把两个来源的集合取并,再给当前格的 数学公式(保留原始 SVG) 配正负号。数学公式(保留原始 SVG) 时两个分支相同,集合原样传下去,不用特判。

集合用 bitset 存,第 数学公式(保留原始 SVG) 位为 数学公式(保留原始 SVG) 表示差值 数学公式(保留原始 SVG) 可达。于是整体加 数学公式(保留原始 SVG) 就是左移 数学公式(保留原始 SVG) 位、整体减 数学公式(保留原始 SVG) 就是右移 数学公式(保留原始 SVG) 位,一次移位处理全部差值。每行只依赖上一行,按列滚动成一维数组 , 数学公式(保留原始 SVG) 被覆盖前存的正是上一行同列。

答案是 数学公式(保留原始 SVG) 中绝对值最小的元素。集合关于 数学公式(保留原始 SVG) 对称(路径上所有格子同时换号仍合法),所以从第 数学公式(保留原始 SVG) 位往高位找第一个 数学公式(保留原始 SVG) 即可。

复杂度分析

时间复杂度:O(HW⌈D/b⌉),D=25441,b 为大整数内部字位数;提取最低可达位另需 O(⌈D/b⌉)。

空间复杂度:O(HW+W⌈D/b⌉) 个机器字,包含两个输入矩阵。

题解代码

import sys
input = sys.stdin.readline

OFF = 159 * 80

def min_balance(h, w, a, b):
    f = [0] * w
    for i in range(h):
        for j in range(w):
            d = abs(a[i][j] - b[i][j])
            if i == 0 and j == 0:
                src = 1 << OFF  # 起点之前差值为 0
            else:
                src = 0
                if i > 0:
                    src |= f[j]  # f[j] 还没被本行覆盖,存的是上一行同列
                if j > 0:
                    src |= f[j - 1]  # 本行左边一格已算好
            f[j] = (src << d) | (src >> d)
    nonnegative = f[w - 1] >> OFF
    return (nonnegative & -nonnegative).bit_length() - 1

h, w = map(int, input().split())
a = []
for _ in range(h):
    a.append(list(map(int, input().split())))
b = []
for _ in range(h):
    b.append(list(map(int, input().split())))

print(min_balance(h, w, a, b), end='')

正确性说明

到当前格的路径只能来自上方或左方,因此合并二者可达集合不重不漏。每个格子的分配只有正负差值两种,移位恰好生成这两个后继。由起点归纳到终点后,集合包含全部合法差值,取最小绝对值即为答案。

易错点与边界

不能只保存每格当前最小差值;起点和终点均参与分配,偏移必须覆盖整个路径差值。

第 2 题:最优笔记排布

题目描述

小明是一位小红书博主,她准备在推荐流的连续 数学公式(保留原始 SVG) 个位置上发布笔记。每个位置都有一个用户互动热度值 数学公式(保留原始 SVG)。她有 数学公式(保留原始 SVG) 篇笔记需要按顺序依次放入推荐流中,第 数学公式(保留原始 SVG) 篇笔记会占据连续的 数学公式(保留原始 SVG) 个位置。我们定义 数学公式(保留原始 SVG) 代表第 数学公式(保留原始 SVG) 篇笔记的起始位置,则该笔记会占据区间 数学公式(保留原始 SVG)

发布时需要满足以下条件:

  1. 所有笔记占据的位置互不重叠,即对于任意 数学公式(保留原始 SVG),有 数学公式(保留原始 SVG);笔记与笔记之间可以留存任意数量的空位置。
  2. 笔记必须按顺序发布,即 数学公式(保留原始 SVG)
  3. 所有笔记必须在推荐流范围内,即 数学公式(保留原始 SVG)数学公式(保留原始 SVG)

我们定义,对每一篇笔记,取其覆盖区间内热度最大值;所有笔记的这些最大值中,最大的那个就是峰值热度。

数学公式(保留原始 SVG)

低调的小明希望找到一个发布方案,使得峰值热度尽可能小。请你帮她求出这个最小值。

输入描述

第一行一个正整数 数学公式(保留原始 SVG),表示测试数据组数。

对于每组测试数据:

第一行两个正整数 数学公式(保留原始 SVG),表示推荐流位置数和笔记篇数,所有测试数据的 数学公式(保留原始 SVG) 之和不超过 数学公式(保留原始 SVG)

第二行 数学公式(保留原始 SVG) 个正整数 数学公式(保留原始 SVG),表示每个位置的热度值。

第三行 数学公式(保留原始 SVG) 个正整数 数学公式(保留原始 SVG),表示每篇笔记占据的位置数。

输出描述

对于每组测试数据,输出一行一个整数,表示峰值热度的最小值。

样例1

输入

2
7 2
5 1 2 4 3 1 2
2 3
5 3
1 3 1 1 2
1 1 1

输出

3
1

样例解释

第一组:将第一篇笔记放在位置 数学公式(保留原始 SVG)(覆盖热度值 数学公式(保留原始 SVG),最大值为 数学公式(保留原始 SVG)),第二篇笔记放在位置 数学公式(保留原始 SVG)(覆盖热度值 数学公式(保留原始 SVG),最大值为 数学公式(保留原始 SVG))。峰值热度为 数学公式(保留原始 SVG)

第二组:将三篇笔记分别放在位置 数学公式(保留原始 SVG)数学公式(保留原始 SVG)数学公式(保留原始 SVG)(覆盖热度值均为 数学公式(保留原始 SVG)),峰值热度为 数学公式(保留原始 SVG)

题解:二分答案 + 贪心

思路分析

数学公式(保留原始 SVG) 段长度固定的区间按顺序、互不重叠地摆进长度 数学公式(保留原始 SVG) 的序列,让所有区间覆盖到的元素最大值尽可能小。

这是一道”最小化最大值”的二分答案题:固定上限 数学公式(保留原始 SVG) 后问题只剩”能不能放下”的判定,而判定贪心扫一遍即可。

算法实现

二分答案:二分峰值热度上限 数学公式(保留原始 SVG)数学公式(保留原始 SVG) 变大时可用位置只增不减,能放下的方案也只增不减,所以可行性关于 数学公式(保留原始 SVG) 单调。峰值本身就是某个位置的热度,答案必等于某个 数学公式(保留原始 SVG),因此只在 数学公式(保留原始 SVG) 去重排序后的数组 数学公式(保留原始 SVG) 上二分。

check 函数:给定 数学公式(保留原始 SVG),热度大于 数学公式(保留原始 SVG) 的位置一律不能被覆盖,从左到右扫描:

  1. 维护当前连续可用的位置数 数学公式(保留原始 SVG),遇到 数学公式(保留原始 SVG)数学公式(保留原始 SVG) 清零。
  2. 数学公式(保留原始 SVG) 恰好等于当前笔记长度 数学公式(保留原始 SVG) 时立刻放下这一篇,令 数学公式(保留原始 SVG)数学公式(保留原始 SVG)
  3. 数学公式(保留原始 SVG) 篇全部放下返回可行,扫完仍没放完返回不可行。

贪心的依据:对任意合法方案归纳,设贪心第 数学公式(保留原始 SVG) 篇结束于 数学公式(保留原始 SVG)、该方案结束于 数学公式(保留原始 SVG),且 数学公式(保留原始 SVG)。方案的第 数学公式(保留原始 SVG) 篇占的 数学公式(保留原始 SVG) 个位置都在 数学公式(保留原始 SVG) 之后,自然也在 数学公式(保留原始 SVG) 之后,所以贪心不晚于方案就能凑够这 数学公式(保留原始 SVG) 个位置。于是贪心放不下,就说明任何方案都放不下。

放下后 数学公式(保留原始 SVG) 直接清零、不留空位,因为条件 数学公式(保留原始 SVG) 允许两篇紧挨。样例第二组取 数学公式(保留原始 SVG) 时,第二、三篇必须紧挨着放在位置 数学公式(保留原始 SVG);误以为要隔一个空位会判不可行,输出 数学公式(保留原始 SVG)

二分过程

  1. 若 check 可行,答案不超过 数学公式(保留原始 SVG),令 数学公式(保留原始 SVG)
  2. 否则 数学公式(保留原始 SVG) 太小,令 数学公式(保留原始 SVG)

输出数学公式(保留原始 SVG) 时输出 数学公式(保留原始 SVG)。题目保证 数学公式(保留原始 SVG)数学公式(保留原始 SVG) 取最大值时所有位置可用、紧挨着放必能放下,二分右端一定可行。

复杂度分析

时间复杂度数学公式(保留原始 SVG)。排序去重 数学公式(保留原始 SVG);二分约 数学公式(保留原始 SVG) 轮,每轮 check 扫一遍 数学公式(保留原始 SVG)。逐个尝试 数学公式(保留原始 SVG)数学公式(保留原始 SVG) 时达 数学公式(保留原始 SVG) 次,二分降到约 数学公式(保留原始 SVG) 次。

空间复杂度数学公式(保留原始 SVG),存 数学公式(保留原始 SVG) 与去重后的 数学公式(保留原始 SVG)

题解代码

import sys
input = sys.stdin.readline

def can_place(a, b, x):
    m = len(b)
    k = 0          # 下一篇要放的笔记编号
    need = b[0]    # 这一篇需要的连续位置数
    run = 0        # 当前连续热度 <= x 的位置数
    for v in a:
        if v > x:
            run = 0
            continue
        run += 1
        if run == need:
            k += 1
            if k == m:
                return True
            need = b[k]
            run = 0
    return False

def min_peak(a, b):
    vals = sorted(set(a))
    lo, hi = 0, len(vals) - 1
    while lo < hi:
        mid = (lo + hi) // 2
        if can_place(a, b, vals[mid]):
            hi = mid
        else:
            lo = mid + 1
    return vals[lo]

t = int(input())
for _ in range(t):
    n, m = map(int, input().split())
    a = list(map(int, input().split()))
    b = list(map(int, input().split()))
    print(min_peak(a, b))

正确性说明

对笔记编号归纳,贪心每篇的结束位置都不晚于任意可行方案:上一篇更早结束不会减少下一篇可用位置。因此贪心失败当且仅当不存在可行方案。阈值变大只增加可用位置,二分得到最小可行阈值。

易错点与边界

两篇笔记可以相邻,不要求额外空位;越过不可用位置后连续可用长度清零。

小结

优先从题面约束提炼模型,再用样例检查边界。本文保留题面数学符号的原始 SVG,代码统一为 Python 3;未给出的评测限制或规则不补作事实。