【春招笔试】2025.05.17淘天机考真题改编题

✅ 春招备战指南 ✅

💡 学习建议:

  • 先尝试独立解题(建议用时:90分钟/套)
  • 对照解析查漏补缺

🧸 题面描述背景等均已深度改编,做法和题目本质基本保持一致。

🍹 感谢各位朋友们的订阅,你们的支持是我们创作的最大动力

🌸 目前本专栏已经上线80+套真题改编解析,后续会持续更新的

春秋招合集 -> 互联网必备刷题宝典🔗

题目一:魔法棋盘构造

1️⃣:构造第一行为自然顺序排列

2️⃣:第二行为循环右移一位的排列,利用相邻整数互质的性质

难度:中等

这道题目的关键在于理解互质性质,并发现使用相邻数互质的规律可以简单构造。通过设计第一行为顺序排列,第二行为循环右移的排列,可以保证相邻格子的数字互质,从而构造出符合条件的魔法棋盘。

题目二:音律旋律序列排列

1️⃣:分析问题本质,确定可行的公差值

2️⃣:针对k=1和k=-1两种情况分别设计特殊构造方法

难度:中等

这道题目结合了数学和构造算法,需要理解等差数列和排列的性质。通过分析发现只有k=1或k=-1时有解,并且可以分别采用从中间向两边扩展或从一端交替向另一端扩展的方式构造排列。

题目三:奇偶平衡树分割问题

1️⃣:计算子树中奇数节点个数的奇偶性

2️⃣:找出"好边"并运用组合数学计算方案数

难度:中等偏难

这道题目需要理解树和子树性质,并结合奇偶性进行分析。通过DFS计算子树内奇数节点数量,找出删除后能使两侧子树奇数节点数为偶数的"好边",再利用组合数学计算从这些好边中选取不同数量边的方案数。

01. 魔法棋盘构造

问题描述

小基 正在设计一款魔法棋盘游戏。游戏棋盘由 的格子组成,每个格子上必须放置从 的数字。棋盘满足以下条件时,称为"魔法棋盘":

  • 第一行包含 的所有数字,每个数字恰好出现一次
  • 第二行也包含 的所有数字,每个数字恰好出现一次
  • 对于任意两个相邻格子(上下或左右相邻)中的数字 ,满足 (即 互质)

现在,小基 想知道对于给定的 值,能否构造出一个魔法棋盘。请你帮助 小基 构造一个满足条件的魔法棋盘,可以证明这样的棋盘始终存在。

输入格式

一个整数 ),表示棋盘的列数。

输出格式

行,每行包含 个用空格分隔的整数,表示构造出的魔法棋盘。若存在多种可能的魔法棋盘,输出任意一种即可。

样例输入

2

样例输出

2 1
1 2
样例 解释说明
样例1 构造出的 魔法棋盘满足:第一行为 [2,1],第二行为 [1,2]。相邻格子的数字分别是 (2,1)、(2,1)、(1,2),它们的最大公约数都是 1,满足互质条件。

数据范围

题解

这个问题要求我们构造一个 的矩阵,使得两行都是 1 到 n 的排列,且相邻位置的数字互质。

关键在于理解互质性质:两个数互质当且仅当它们的最大公约数为 1。相邻整数(如 3 和 4)总是互质的,因为它们没有共同因子。

考虑一种简单的构造方法:

  1. 将第一行设为自然顺序:1, 2, 3, ..., n
  2. 将第二行设为循环右移一位:2, 3, ..., n, 1

这样构造的矩阵满足条件吗?让我们验证:

  • 第一行和第二行显然是排列
  • 对于同一列的两个数,如第 i 列的 i 和 i+1(或者 n 和 1),它们是相邻整数,因此互质
  • 对于相邻列的数,第一行中 i 和 i+1 是相邻整数,互质;第二行中 i+1 和 i+2 也是相邻整数,互质

这种构造方法的时间复杂度是 O(n),只需要简单地生成两个数组即可。在实际代码中,只需要两个循环输出这两个排列。

这个解法的优雅之处在于利用了数论中的一个基本性质:相邻整数总是互质的。无需复杂的计算或验证,只需按特定方式排列数字就能保证满足所有条件。

参考代码

  • Python
import sys
input = lambda: sys.stdin.readline().strip()

def sol():
    # 读取输入
    n = int(input())
    
    # 输出第一行:1, 2, ..., n
    row1 = [str(i) for i in range(1, n+1)]
    print(' '.join(row1))
    
    # 输出第二行:2, 3, ..., n, 1
    row2 = [str((i % n) + 1) for i in range(1, n+1)]
    print(' '.join(row2))

if __name__ == "__main__":
    sol()
  • Cpp
#include <iostream>
using namespace std;

int main() {
    // 优化输入输出
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    // 读取输入
    int n;
    cin >> n;
    
    // 输出第一行:1,2,...,n
    for (int i = 1; i <= n; ++i) {
        cout << i;
        if (i < n) cout << " ";
        else cout << "\n";
    }
    
    // 输出第二行:2,3,...,n,1
    for (int i = 1; i <= n; ++i) {
        // 计算循环右移后的值
        int val = (i % n) + 1;
        cout << val;
        if (i < n) cout << " ";
        else cout << "\n";
    }
    
    return 0;
}
  • Java
import java.io.*;
import java.util.*;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        // 读取输入
        int n = Integer.parseInt(br.readLine().trim());
        
        StringBuilder sb = new StringBuilder();
        
        // 构造第一行:1,2,...,n
        for (int i = 1; i <= n; i++) {
            sb.append(i);
            if (i < n) sb.append(" ");
        }
        sb.append("\n");
        
        // 构造第二行:2,3,...,n,1
        for (int i = 1; i <= n; i++) {
            int val = (i % n) + 1;
            sb.append(val);
            if (i < n) sb.append(" ");
        }
        
        System.out.println(sb);
    }
}

02. 音律旋律序列排列

问题描述

小毛是一位音乐家,他正在创作一个新的音乐序列。他希望通过精心设计音符的排列,让相邻音符的音高差形成一个等差数列,以创造出特殊的旋律效果。

具体来说,小毛有 个不同音高的音符,分别编号为 。他想将这些音符排成一个序列 ,使得相邻音符的音高差的绝对值构成一个等差为 的等差数列。

形式化地,假设排列 的下标从 开始,我们定义长度为 的数组 ,其中对于 ,有 。若数组 是一个公差为 的等差数列,则称排列 是一个"音律序列"。

小毛给定整数 ,请你帮助他构造一个音律序列,或者判断这样的序列是否存在。

输入格式

一行两个整数 ),表示音符的数量和等差数列的公差。

输出格式

若存在满足条件的排列,第一行输出"YES",第二行输出 个整数,每个整数用空格隔开,表示满足条件的排列。若不存在则输出"NO"。

样例输入

4 -1

样例输出

YES
1 4 2 3
6 4
NO
样例 解释说明
样例1 排列为 [1,4,2,3],相邻元素差的绝对值为 ,公差为 ,符合题意。
样例2 无法构造长度为 6 且公差为 4 的音律序列。

数据范围

题解

这个问题要求构造一个特殊的排列,使得相邻元素差的绝对值构成公差为k的等差数列。先分析问题的本质:

假设我们构造的排列是 ,那么对应的差值序列是

这个差值序列需要是公差为k的等差数列,也就是形如

关键问题在于:什么样的k值能够让我们构造出合法的排列?

经过分析,可以发现:

  1. 时,差值序列是
  2. 时,差值序列是
  3. 对于其他k值,无法保证构造出的序列是一个合法的排列(会有重复元素或超出范围的元素)

为什么只有这两种情况?考虑一下,排列中的元素只能取1到n,差值的绝对值最大为n-1,最小为1。如果公差k不是1或-1,那么差值序列会迅速增大或减小,无法用1到n的排列实现。

对于k=1的情况,可以从中间元素开始,交替向两边扩展。 对于k=-1的情况,可以从一端开始,交替往另一端构造。

具体构造方法:

  • 当k=1时:从 开始,交替加减递增的数
  • 当k=-1时:从1开始,交替加减递减的数

通过这种方式,我们能够构造出符合条件的排列。时间复杂度为O(n),空间复杂度为O(n)。

参考代码

  • Python
import sys
input = lambda: sys.stdin.readline().strip()

def solve():
    # 读取输入
    n, k = map(int, input().split())
    
    # 只有k=1或k=-1时有解
    if k == 1:
        # 输出YES
        print("YES")
        
        # 构造排列
        p = [0] * n
        mid = (n + 1) // 2  # 中间位置
        p[0] = mid  # 起始元素
        
        # 交替向两边扩展
        for i in range(1, n):
            if i % 2 == 1:
                p[i] = p[i-1] + i  # 向上扩展
            else:
                p[i] = p[i-1] - i  # 向下扩展
                
        # 输出结果
        print(" ".join(map(str, p)))
        
    elif k == -1:
        # 输出YES
        print("YES")
        
        # 构造排列
        p = [0] * n
        p[0] = 1  # 起始元素
        
        # 交替加减构造
        for i in range(1, n):
            d = n - i  # 递减的差值
            if i % 2 == 1:
                p[i] = p[i-1] + d
            else:
                p[i] = p[i-1] - d
                
        # 输出结果
        print(" ".join(map(str, p)))
        
    else:
        # 其他情况无解
        print("NO")

if __name__ == "__main__":
    solve()
  • Cpp
#include <iostream>
#include <vector>
using namespace std;

int main() {
    // 优化输入输出
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    // 读取输入
    int n, k;
    cin >> n >> k;
    
    // 判断是否有解
    if (k == 1) {
        // 输出YES
        cout << "YES" << endl;
        
        // 构造排列
        vector<int> p(n);
        int mid = (n + 1) / 2;
        p[0] = mid;
        
        for (int i = 1; i < n; ++i) {
            if (i % 2 == 1)
                p[i] = p[i-1] + i;
            else
                p[i] = p[i-1] - i;
        }
        
        // 输出结果
        for (int i = 0; i < n; ++i) {
            cout << p[i] << (i == n-1 ? '\n' : ' ');
        }
    }
    else if (k == -1) {
        // 输出YES
        cout << "YES" << endl;
        
        // 构造排列
        vector<int> p(n);
        p[0] = 1;
        
        for (int i = 1; i < n; ++i) {
            int d = n - i;
            if (i % 2 == 1)
                p[i] = p[i-1] + d;
            else
                p[i] = p[i-1] - d;
        }
        
        // 输出结果
        for (int i = 0; i < n; ++i) {
            cout << p[i] << (i == n-1 ? '\n' : ' ');
        }
    }
    else {
        // 其他情况无解
        cout << "NO" << endl;
    }
    
    return 0;
}
  • Java
import java.io.*;
import java.util.*;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        
        // 读取输入
        String[] parts = br.readLine().trim().split(" ");
        int n = Integer.parseInt(parts[0]);
        int k = Integer.parseInt(parts[1]);
        
        // 判断是否有解
        if (k == 1) {
            // 输出YES
            System.out.println

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

互联网刷题笔试宝典 文章被收录于专栏

互联网刷题笔试宝典,这里涵盖了市面上大部分的笔试题合集,希望助大家春秋招一臂之力

全部评论

相关推荐

06-05 00:54
已编辑
北京邮电大学 前端工程师
蹲个女生舍友,杭州西溪。--------------以下是正文--------------先说一下我个人情况,北邮通信工程,我在本科的时候做过几个微信小程序,忘光了。在今年2月份开始极速学习前端基础。代码算法方面,研一和大四的时候跟着代码随想录刷过一次。轻微流水账,这是一个记录贴。初衷希望能给0实习转码的同学一些鼓励,相信一定能找到愿意培养自己的公司。第一次找工作没什么经验,秋招会及时复盘面经发出来,这次就先不弄了。我从1月份就开始调研咋学习前端,开始慢悠悠学习html和css知识,到二月份开学了才开始对暑期实习感到十分的担忧,开始拼命学js。之前就接触过相关内容所以学的很快,半个月左右就学完了。然后就开始一边学习react一边做项目。4月初开始陆续投递,等了一周就开始有面试了。第一个面的美团,上来就是一个hard代码题,hot100还没刷完的我感到十分挫败。五月中旬之前,我一直处于反复一面的状态。基本上一天三面。晚上还得做笔试。崩溃边缘,但是还得鼓励(欺骗)自己下周必拿offer。或许是乐观的心态,让我在16号以后开始收到一些公司的二面了。包括美团,阿里(智能信息),腾讯,字节。我非常高兴,说明我五一不出去玩,恶补八股和手撕是真的有用。运气好了之后就开始一直破天荒的好。我阿里的淘天和阿里云也进二面了。我记得自己虽然表现的还行,但是整体并不突出。5月20/21号,这两天是小情侣过节的日子。我记得我20号面了美团,阿里智能信息二面,21号面了腾讯,字节,淘天二面,晚上还做了一个笔试。累的半死的同时,实验室导师还在催我的科研进度,我回复:好的。没想到,阿里智能信息居然问了我通信原理,本科学科等很多很泛的问题。我以为要凉了,结果没过一个小时,hr联系我:你好,你的二面已经通过,需要您再做一个线上笔试。我欣喜若狂,不敢相信二面居然问这些都能过。笔试做完了之后,也是立马有hr联系我,约hr面。5月22号,hr面。当场发offer,我整个人都懵了。心里怀疑对方是不是诈骗公司,然后又反复确认。缓了半天,才发现自己居然能去阿里了。简直是做梦都不敢想。我记得我前几天面试压力太大,还梦到过实验室组会汇报自己的offer进度,大家都去阿里。而我连甚至一个offer都没有可以汇报。当场吓醒。最后必须说,阿里真的太好了,愿意相信实习生的潜力,真的给了很多0实习的同学实习机会。我永远是阿里孝女!!!!!---------------分割线-----------记录一下自己转码以来遇到的一些贵人。1.字节的一面面试官,在我最崩溃的时候给了我鼓励和肯定。当时给我面了一个半小时。最后我问他对建议的时候,他说,“你是候选人里面算是比较优秀的了,但是我们这个业务要求很高,我担心把你招进来影响你的成长。”并且还给我推荐学习资料,红宝书。还和我说,“如果你想要继续做前端的话,我可以告诉你,前端依然是十分有前途的方向,希望你可以继续努力。”他的话真的十分中肯。当时我甚至感动哭了,我非常清楚自己不是因为被拒绝哭了(毕竟其实已经麻了)2.腾讯的一位面试官。给了我很多叮咛,告诉我准备好在面试等等。让我感觉十分有力量,我当时觉得我身边那么多帮助我的好人,我怎么可能不成功呢。3.北邮的一位学长,他在一开始给了我职业选择方面的建议,让我坚定了自己的道路。4.我遇到的每一个面试官都出奇的好,没有因为我很菜就表现不耐烦,十分感恩他们的手下留情。5.感谢有对象的陪伴,让我有好好吃饭的动力,并且也一直督促我学习,还帮我把一些高频的手撕和高频的计算机相关的八股梳理出来。有的时候真的想放弃,但是他一直在我旁边和我说,一定要坚持,不能放弃。
点赞 评论 收藏
分享
评论
2
2
分享
牛客网
牛客网在线编程
牛客网题解
牛客企业服务