【秋招笔试】2025.09.11阿里云秋招算法岗笔试真题改编

✅ 秋招备战指南 ✅

💡 学习建议:

  • 先尝试独立解题
  • 对照解析查漏补缺

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

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

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

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

阿里云

题目一:能量石属性统一

1️⃣:统计火属性(奇数)和水属性(偶数)能量石的数量

2️⃣:根据融合规律分析,若有水属性则答案为火属性数量,否则为0

难度:中等

这道题目的核心在于理解能量石属性融合的数学规律。通过观察奇数和偶数的运算性质,可以发现只要存在偶数(水属性),最终结果只能是全偶数;若全为奇数(火属性),则无需操作。利用数学推导可得出 O(n) 的高效解法。

题目二:工厂设备异常检测系统

1️⃣:使用StandardScaler对合并数据进行标准化处理

2️⃣:基于PCA降维重构计算误差,设置95百分位阈值检测异常

难度:中等

这道题目结合了数据预处理和机器学习中的PCA异常检测算法。核心思想是利用PCA重构误差来识别异常数据,正常数据的重构误差较小,而异常数据由于偏离正常分布模式会产生较大的重构误差。

题目三:线性网络信号传播

1️⃣:将手动激活看作信号源,按时间和位置记录

2️⃣:分析左端、右端和中间区间,计算信号传播的最远距离

3️⃣:使用数学公式求解两信号源交汇处的最晚激活时间

难度:中等偏难

这道题目本质上是多源最短路径问题,需要理解信号传播的时空关系。通过将问题转化为一维多源BFS,利用数学分析计算各区间的最晚激活时间,最终取最大值。关键在于处理信号源的去重和区间分析,实现 O(m log m) 的高效算法。

01. 能量石属性统一

问题描述

小兰是一名能量石收集者,她收集了 块能量石排成一排。每块能量石都有自己的能量值,并且具有两种属性之一:火属性或水属性。

  • 如果能量石的能量值为奇数,则该能量石具有火属性
  • 如果能量石的能量值为偶数,则该能量石具有水属性

小兰希望通过融合操作,让所有能量石都变成同一种属性(全部为火属性或全部为水属性)。

融合规则:可以选择两个相邻的能量石进行融合,融合后会产生一块新的能量石,其能量值等于原来两块能量石能量值的乘积,并替代原来的两块能量石。

根据能量石的属性融合规律:

  • 火属性 + 火属性 = 火属性(奇数 × 奇数 = 奇数)
  • 火属性 + 水属性 = 水属性(奇数 × 偶数 = 偶数)
  • 水属性 + 水属性 = 水属性(偶数 × 偶数 = 偶数)

请计算最少需要多少次融合操作,才能让所有能量石都变成同一种属性。

输入格式

每个测试文件包含多组测试数据。第一行包含一个正整数 ),表示测试数据的组数。

对于每组测试数据:

第一行包含一个正整数 ),表示能量石的数量。

第二行包含 个正整数 ),表示每块能量石的能量值。

保证单个测试文件中所有 值的总和不超过

输出格式

对于每组测试数据,输出一行包含一个整数,表示使所有能量石变成同一种属性所需的最少融合操作次数。

样例输入

2
2
1 2
3
2 3 2

样例输出

1
1
样例 解释说明
样例1 ,能量石序列为 ,对应属性为 火, 水。进行一次融合操作:,得到 (全为水属性),答案为
样例2 ,能量石序列为 ,对应属性为 水, 火, 水。融合后两个能量石:,得到 (全为水属性),答案为

数据范围

  • 保证单个测试文件中所有 值的总和不超过

题解

这道题的关键在于理解能量石属性融合的规律。

通过观察融合规则,我们可以发现:

  • 火属性(奇数)与火属性(奇数)融合后仍然是火属性(奇数)
  • 火属性(奇数)与水属性(偶数)融合后变成水属性(偶数)
  • 水属性(偶数)与水属性(偶数)融合后仍然是水属性(偶数)

这意味着:

  1. 如果序列中存在至少一块水属性能量石,那么最终只能得到全水属性的结果,因为水属性与任何属性融合都会产生水属性
  2. 如果序列中全部都是火属性能量石,那么已经满足条件,无需操作
  3. 当存在水属性能量石时,我们需要让所有火属性能量石都与水属性能量石融合,每个火属性能量石需要一次融合操作来消除

设火属性能量石的数量为 ,水属性能量石的数量为 ,则答案为:

算法步骤:

  1. 遍历所有能量石,统计火属性(奇数)和水属性(偶数)的数量
  2. 如果没有水属性能量石,返回
  3. 如果有水属性能量石,返回火属性能量石的数量

时间复杂度: 空间复杂度:

参考代码

Python

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

def solve():
    # 读取测试数据组数
    t = int(input())
    
    for _ in range(t):
        # 读取能量石数量
        n = int(input())
        # 读取能量石能量值
        stones = list(map(int, input().split()))
        
        # 统计火属性(奇数)和水属性(偶数)能量石的数量
        fire_cnt = 0  # 火属性计数
        water_cnt = 0  # 水属性计数
        
        for val in stones:
            if val % 2 == 1:  # 奇数为火属性
                fire_cnt += 1
            else:  # 偶数为水属性
                water_cnt += 1
        
        # 如果没有水属性能量石,已经全为火属性,无需操作
        if water_cnt == 0:
            print(0)
        else:
            # 有水属性能量石,需要消除所有火属性能量石
            print(fire_cnt)

solve()

Cpp

#include <iostream>
#include <vector>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int t;
    cin >> t;
    
    while (t--) {
        int n;
        cin >> n;
        
        int fire = 0, water = 0;  // 火属性和水属性计数
        
        for (int i = 0; i < n; i++) {
            int val;
            cin >> val;
            
            if (val & 1) {  // 使用位运算判断奇偶性
                fire++;
            } else {
                water++;
            }
        }
        
        // 如果没有水属性能量石,答案为0;否则答案为火属性数量
        cout << (water == 0 ? 0 : fire) << "\n";
    }
    
    return 0;
}

Java

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int testCase = sc.nextInt();
        
        while (testCase-- > 0) {
            int stoneNum = sc.nextInt();
            
            int fireCnt = 0, waterCnt = 0;  // 火水属性计数器
            
            for (int i = 0; i < stoneNum; i++) {
                int energy = sc.nextInt();
                
                if ((energy & 1) == 1) {  // 奇数检测(火属性)
                    fireCnt++;
                } else {  // 偶数(水属性)
                    waterCnt++;
                }
            }
            
            // 输出结果:无水属性时为0,否则为火属性数量
            System.out.println(waterCnt == 0 ? 0 : fireCnt);
        }
        
        sc.close();
    }
}

02. 工厂设备异常检测系统

问题描述

小毛是一家工厂的质量检测工程师,负责开发设备异常检测系统。工厂中的关键设备配备了多个传感器,用于监控设备的运行状态。

小毛需要基于历史正常运行的传感器数据,构建一个异常检测模型,用于判断新的传感器读数是否表示设备异常。他决定使用基于 PCA(主成分分析)重构误差的方法来实现异常检测。

请在仅使用 numpy/pandas/scikit-learn 的前提下,实现这个异常检测算法,对测试样本判定"正常 /异常 "。

检测算法的具体步骤如下:

  1. 数据读取

    • train:二维列表,包含历史正常运行时的传感器数据(无标签)
    • test:二维列表,包含待检测的传感器数据(与 train 具有相同的特征维度)
  2. 数据标准化

    • 使用 StandardScaler 对数据进行标准化处理
    • 必须将 traintest 数据拼接后一次性进行 fit_transform,以避免数据分布不一致的问题
  3. 主成分分析与重构

    • 对拼接后的标准化数据进行 PCA 降维,使用固定参数:n_components=1, svd_solver="full", random_state=42
    • 在标准化数据上训练 PCA 模型,然后分别对数据进行 transforminverse_transform 操作,获得重构后的数据
  4. 重构误差计算与阈值设定

    • 对训练数据部分,计算每个样本的重构误差:
    • 将训练数据重构误差的第 百分位数作为异常检测的阈值
    • 异常判别准则:
  5. 结果输出

    • 仅输出 test 部分的预测标签序列
    • 以单行 JSON 数组格式输出,如 [0, 1]
    • 输出顺序必须与输入 test 数据的顺序保持一致

输入格式

标准输入包含一行 JSON 格式的数据,示例如下:

{
  "train": [[0, 0], [0.1, 0], [0, -0.1], [0.05, 0.05]],
  "test": [[0.04, 0.02], [3, 3]]
}

输入数据的要求:

  • 传感器数据至少包含二维特征
  • 所有数值为整数或浮点数,无缺失值

输出格式

输出一行 JSON 数组格式的结果,如:[0, 1]

要求:

  • 数组长度等于测试样本数量
  • 输出格式为合法的 JSON,逗号后包含空格

样例输入

{"train":[[0,0],[0.1,0],[0,-0.1],[0.05,0.05],[0.2,0.1],[0.1,-0.1]],"test":[[0.05,0],[0.2,-0.6],[0.1,0.1],[0.2,0]]}

样例输出

[0, 0, 0, 0]
样例 解释说明
样例1 训练数据包含6组传感器读数,都是接近原点的正常数据。测试数据包含4组读数,经过PCA重构误差分析后,所有测试样本的重构误差都在正常范围内(小于等于第95百分位阈值),因此都被判定为正常(标签0)

数据范围

  • 传感器特征维度
  • 训练样本数量和测试样本数量由具体测试用例决定
  • 数值范围:实数

题解

这道题要求实现基于 PCA 重构误差的异常检测算法,这是一种经典的无监督异常检测方法。

算法原理: PCA(主成分分析)可以将高维数据投影到低维空间,然后再重构回原始维度。对于正常数据,由于其分布相对规律,重构误差通常较小;而异常数据由于偏离了正常的数据分布模式,其重构误差往往较大。

实现步骤:

  1. 数据预处理:将训练和测试数据合并进行标准化,确保数据分布一致
  2. PCA训:在标准化数据上训练PCA模型,降维到1维主成分

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

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

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

全部评论

相关推荐

评论
点赞
收藏
分享

创作者周榜

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