【秋招笔试】2025届小红书秋招笔试真题改编卷第一套
要参加小红书笔试了?来看看去年的小红书秋招题目长啥样吧
✅ 秋招备战指南 ✅
💡 学习建议:
- 先尝试独立解题
- 对照解析查漏补缺
🧸 题面描述背景等均已深度改编,做法和题目本质基本保持一致。
🍹 感谢各位朋友们的订阅,你们的支持是我们创作的最大动力
🌸 目前本专栏已经上线100+套真题改编解析,后续会持续更新的
春秋招笔试机考招合集 -> 互联网必备刷题宝典🔗
题目一:山峰探险
1️⃣:定义特定条件的"山峰数组",要求有一个最高点,两侧严格递减
2️⃣:通过预处理每个位置的左侧递增长度和右侧递减长度
3️⃣:遍历数组找出最长满足条件的子数组
难度:中等
这道题目要求在数组中找出特定模式的子数组。通过预处理技巧,我们可以在O(n)的时间内解决问题,避免了暴力枚举所有子数组的高复杂度。关键在于理解"山峰数组"的定义,并巧妙利用两次遍历来记录关键信息。
题目二:小兰的美观排列
1️⃣:理解"不美观程度"的定义:相邻两本书类别不同的情况数
2️⃣:使用动态规划计算最优解,状态转移考虑固定书和可移动书
3️⃣:通过记忆化搜索优化状态空间,降低计算复杂度
难度:中等
这道题目结合了组合优化和动态规划思想,需要找出一种排列方式使"不美观程度"最小。通过巧妙设计状态表示和转移方程,我们可以在O(n²)的时间复杂度内解决问题,有效处理题目给定的数据范围。
题目三:小兰的彩色树木园
1️⃣:在树结构中寻找最优切割点(红色节点)
2️⃣:通过深度优先搜索计算每个子树中黑色节点的数量
3️⃣:对每个红色节点评估切割后黑色节点的最大连通分量
难度:中等偏难
这道题目是典型的树形DP问题,需要理解树的连通性和切割操作对结构的影响。通过一次DFS遍历,我们可以获取解决问题所需的所有信息,并在O(n)的时间复杂度内找到最优解,展现了图算法在实际问题中的应用。
01. 山峰探险
问题描述
K 小姐是一位热爱探险的旅行者,她对山峰情有独钟。最近,她在一片神秘的山脉中发现了一些连续的山峰。为了研究这些山峰的形状,她决定将山峰的高度记录下来,并寻找其中最长的"山峰数组"。
一个"山峰数组"定义为:在某个位置存在一个最高点,且该位置左右两边的高度依次严格递减。用数学语言描述,即存在  使得 
 且 
。例如,
 和 
 是"山峰数组",而 
, 
, 
 和 
 不是。
K 小姐想知道,在她记录的所有子数组中,最长的"山峰数组"的长度是多少。
输入格式
第一行输入一个整数 ,表示数组的长度 
。
第二行输入  个整数 
,表示数组的值 
。
输出格式
输出一个整数,表示最长的"山峰数组"的长度。
样例输入
6
1 1 4 5 1 4
样例输出
4
| 样例 | 解释说明 | 
|---|---|
| 样例1 | 最长的"山峰数组"是 | 
数据范围
- 数组长度 满足 。 
- 数组元素 满足 。 
题解
这道题目要求我们找出给定数组中,满足"山峰数组"定义的最长子数组长度。
首先,我们需要清楚理解"山峰数组"的定义:它必须有一个最高点,且这个最高点左边的元素严格递增,右边的元素严格递减。
解决这个问题的关键在于,我们可以预处理出每个位置的两个信息:
- 该位置左侧的严格递增长度
- 该位置右侧的严格递减长度
我们可以通过两次遍历数组来完成这个预处理:
- 从左到右遍历数组,计算每个位置的左侧严格递增长度
- 从右到左遍历数组,计算每个位置的右侧严格递减长度
然后,对于每个位置 i,如果它左侧有递增序列且右侧有递减序列,那么以 i 为最高点的"山峰数组"长度就是:左侧长度 + 右侧长度 + 1(当前位置本身)。
我们只需要找出所有可能的"山峰数组"中长度最大的那个。
时间复杂度分析:
- 两次遍历预处理数组:O(n)
- 一次遍历计算最大长度:O(n)
- 总时间复杂度:O(n),其中 n 是数组的长度
这个复杂度对于题目给定的数据范围(n ≤ 10^5)是完全可以接受的。
参考代码
- Python
import sys
input = lambda:sys.stdin.readline().strip()
def solve():
    n = int(input())
    nums = list(map(int, input().split()))
    
    # 预处理左侧严格递增长度
    left = [0] * n
    for i in range(1, n):
        if nums[i] > nums[i-1]:
            left[i] = left[i-1] + 1
    
    # 预处理右侧严格递减长度
    right = [0] * n
    for i in range(n-2, -1, -1):
        if nums[i] > nums[i+1]:
            right[i] = right[i+1] + 1
    
    # 计算最大山峰长度
    ans = 0
    for i in range(n):
        if left[i] > 0 and right[i] > 0:
            ans = max(ans, left[i] + right[i] + 1)
    
    return ans
print(solve())
- Cpp
#include <iostream>
#include <vector>
using namespace std;
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int n;
    cin >> n;
    
    vector<int> a(n);
    for (int i = 0; i < n; i++) {
        cin >> a[i];
    }
    
    // 计算左侧递增序列长度
    vector<int> left(n);
    for (int i = 1; i < n; i++) {
        if (a[i] > a[i-1]) {
            left[i] = left[i-1] + 1;
        }
    }
    
    // 计算右侧递减序列长度
    vector<int> right(n);
    for (int i = n-2; i >= 0; i--) {
        if (a[i] > a[i+1]) {
            right[i] = right[i+1] + 1;
        }
    }
    
    // 计算最长山峰数组
    int res = 0;
    for (int i = 0; i < n; i++) {
        if (left[i] > 0 && right[i] > 0) {
            res = max(res, left[i] + right[i] + 1);
        }
    }
    
    cout << res << endl;
    return 0;
}
- Java
import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        
        int[] nums = new int[n];
        for (int i = 0; i < n; i++) {
            nums[i] = sc.nextInt();
        }
        
        // 计算左侧递增序列
        int[] left = new int[n];
        for (int i = 1; i < n; i++) {
            if (nums[i] > nums[i-1]) {
                left[i] = left[i-1] + 1;
            }
        }
        
        // 计算右侧递减序列
        int[] right = new int[n];
        for (int i = n-2; i >= 0; i--) {
            if (nums[i] > nums[i+1]) {
                right[i] = right[i+1] + 1;
            }
        }
        
        // 寻找最长山峰数组
        int maxLen = 0;
        for (int i = 0; i < n; i++) {
            if (left[i] > 0 && right[i] > 0) {
                maxLen = Math.max(maxLen, left[i] + right[i] + 1);
            }
        }
        
        System.out.println(maxLen);
        sc.close();
    }
}
02. 小兰的美观排列
问题描述
小兰最近在整理她的书架,她希望将书架上的书分为两类,并且将它们排成一排。为了让书架看起来更美观,她希望相邻的书尽量属于同一类别。每当相邻的两本书属于不同的类别时,小兰就会觉得不美观。
书架上的一些书已经固定不能移动,而其他书可以自由移动。小兰想知道,如何移动这些可以移动的书籍,使得不美观程度最小。
输入格式
第一行输入一个整数 ,表示书的数量。
第二行输入  个整数 
,表示书的类别。其中 
 表示书是第一类,
 表示书是第二类。
第三行输入  个整数 
,表示书是否可以移动。其中 
 表示第 
 本书可以移动,
 表示第 
 本书不可以移动。
输出格式
输出一个正整数,表示不美观程度的最小值。
样例输入
5
1 2 1 2 1
0 1 1 0 1
样例输出
1
| 样例 | 解释说明 | 
|---|---|
| 样例1 | 初始时第2、3、5本书可以移动。可以将第2本书改为类别1,第3本书改为类别2。经过调整后,书架变为[1,1,2,2,1],只有第4本书和第5本书之间不美观,所以不美观程度为1。 | 
数据范围
题解
这道题目可以使用动态规划来解决。首先,我们需要明确什么是"不美观程度"——即相邻两本书类别不同的情况数量。
我们定义状态 dp[i][j][k] 表示:处理到第 i 本书时,还剩余 j 本第一类可移动的书,当前这本书的类别为 k(0表示第一类,1表示第二类)时的最小不美观程度。
状态转移思路如下:
- 如果当前书不可移动(b[i] = 0),我们只能保持它的原始类别,计算与前一本书的不美观程度(如果存在)。
- 如果当前书可以移动(b[i] = 1),我们有两种选择: 
    - 放置第一类书
- 放置第二类书(如果还有剩余的第一类可移动书)
 
- 我们选择这两种情况中不美观程度较小的一种。
动态规划的边界条件是:当处理完所有书时(i = n),如果没有剩余的可移动书(j = 0),则返回0;否则返回一个很大的值(表示非法状态)。
这个问题的关键在于理解可移动书籍的分配:最初,我们统计可移动的第一类书的数量 t,然后在动态规划过程中,每当我们选择将一本可移动的书放置为第二类时,就减少一本可移动的第一类书。
时间复杂度分析:
- 状态数量:O(n²),因为我们有 n 本书,每本书有至多 n 种剩余第一类可移动书的状态,以及2种当前书的类别。
- 每个状态的转移时间:O(1)
- 因此,总时间复杂度为 O(n²),对于题目给定的 n ≤ 100,这个复杂度是可以接受的。
参考代码
- Python
import sys
sys.setrecursionlimit(10**7)
input = lambda: sys.stdin.readline().strip()
def solve():
    n = int(input())
    a = list(map(int, input().split()))
    b = list(map(int, input().split()))
    
    # 将类别转换为0和1
    for i in range(n):
        a[i] -= 1
    
    # 统计可移动的第二类书的数量
    count = 0
    for i in range(n):
        if b[i] == 1 and a[i] == 1:
            count += 1
    
    # dp数组初始化为None表示未计算
    dp = [[[None for _ in range(2)] for _ in range(count+1)] for _ in range(n+1)]
    
    def dfs(pos, rem, prev):
        # 处理完所有书
        if pos == n:
            return 0 if rem == 0 else 10**9  # 用大数代替inf
        
        if dp[pos][rem][prev] is not None:
            return dp[pos][rem][prev]
        
        # 计算惩罚:如果不是第一本书,且当前类别与前一本不同,惩罚1,否则0
        # 当前书类别暂时未知,先尝试不同放法
        res = 10**9
        
        if b[pos] == 1:
            # 放第一类书
            pen = 0 if pos == 0 else (1 if prev != 0 else 0)
            res = min(res, dfs(pos+1, rem, 0) + pen)
            
            # 放第二类书(前提是还有剩余rem)
            if rem > 剩余60%内容,订阅专栏后可继续查看/也可单篇购买
互联网刷题笔试宝典,这里涵盖了市面上大部分的笔试题合集,希望助大家春秋招一臂之力
 海康威视公司福利 1137人发布
海康威视公司福利 1137人发布