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

✅ 秋招备战指南 ✅

💡 学习建议:

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

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

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

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

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

题目一:小兰的魔法阵列

1️⃣:分析魔法操作对相邻元素差值的影响

2️⃣:枚举所有可能的起始位置计算最小区间长度

3️⃣:利用数学公式 计算所需长度

难度:中等

这道题目的关键在于理解魔法操作的本质:在区间左端制造"跳跃"来产生大的相邻差值。通过数学分析,我们可以得到一个 的高效解法,避免了暴力枚举所有可能的区间。

题目二:小基的数据分析实验

1️⃣:实现标准的K-Means聚类算法(K=3)

2️⃣:使用欧氏距离进行样本分配和质心更新

3️⃣:按字典序对质心排序并重新映射标签

难度:中等

这道题目结合了机器学习算法的实现,需要理解K-Means聚类的核心思想和迭代过程。通过正确实现距离计算、质心更新和收敛判断,可以完成对测试数据的准确分类。

题目三:小毛的闯关之旅

1️⃣:将问题转化为最长严格递增子序列(LIS)问题

2️⃣:对每个关卡内的守卫按实力值升序排序

3️⃣:使用二分优化的LIS算法求解,时间复杂度

难度:中等偏难

这道题目的核心是发现游戏规则与LIS问题的等价性。由于关卡的顺序性和实力值的增长规律,问题可以转化为在有序序列中寻找最长严格递增子序列,通过二分优化可以达到理想的时间复杂度。

01. 小兰的魔法阵列

问题描述

小兰是一位年轻的魔法师,她最近在研究一种特殊的魔法阵列。这个魔法阵列是一个长度为 非严格递增序列

小兰可以施展一次强力的魔法咒语,选择一个连续的区间 ,对区间内的每个位置 施加魔法:

也就是说,区间内从左到右的每个元素分别增加

小兰希望通过这次魔法操作,使得阵列中至少存在一个位置 满足 ,即相邻两个元素的差值超过阈值

请帮助小兰找到能够实现这个目标的最小区间长度(区间长度可以为 ,表示不进行任何操作)。如果无论如何都无法实现目标,输出

名词解释非严格递增序列:对于任意 ,都有

输入格式

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

对于每组测试数据:

第一行包含三个正整数 ,其中

第二行包含 个正整数 ,其中 ,保证序列非严格递增。

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

输出格式

对于每组测试数据,输出一个整数,表示满足条件的最小区间长度。

样例输入

2
4 3 2
1 2 3 4
3 5 1
2 4 6
3
2 0 1
1 1
4 0 2
1 2 3 5
6 10 4
1 2 2 4 6 9

样例输出

2
-1
1
0
0
样例 解释说明
样例1-1 选择区间 (长度为2),数组变为 ,其中 满足条件
样例1-2 无论如何操作都无法使相邻差值超过5,输出-1
样例2-1 选择区间 (长度为1),数组变为 ,其中 满足条件
样例2-2 原数组已存在相邻差值 ,无需操作,输出0
样例2-3 原数组已存在相邻差值超过10的情况,无需操作,输出0

数据范围

题解

这道题的核心思想是分析魔法操作对相邻元素差值的影响。

首先考虑几种特殊情况:

  1. 如果原数组已经存在相邻差值大于 的情况,那么答案就是
  2. 如果我们只对一个元素施法(区间长度为1),被修改的元素会增加 ,如果 ,那么答案就是

对于一般情况,关键观察是:要想产生大的相邻差值,最有效的方法是在区间的左端点制造"跳跃"。

设相邻元素的差值为 )。如果我们选择以位置 为左端点、长度为 的区间进行操作,那么操作后:

要使这个差值大于 ,需要满足:

因此,对于每个可能的起始位置 ,我们需要的最小区间长度为:

但是还要考虑区间不能超出数组边界的限制:区间 必须满足 ,即

最终答案就是所有满足条件的 中的最小值。

算法步骤:

  1. 检查原数组是否已满足条件
  2. 检查单个元素操作是否可行
  3. 枚举每个可能的起始位置,计算所需的最小区间长度
  4. 返回所有可行方案中的最小长度

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

参考代码

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

def solve():
    n, d, m = map(int, input().split())
    a = list(map(int, input().split()))
    
    # 检查原数组是否已满足条件
    for i in range(1, n):
        if abs(a[i] - a[i-1]) > d:
            return 0
    
    # 如果单个元素操作就能满足条件
    if m > d:
        return 1
    
    # 枚举所有可能的起始位置
    ans = float('inf')
    for i in range(1, n):
        gap = a[i] - a[i-1]  # 当前相邻差值
        if gap > d:  # 已经满足条件
            ans = 0
            break
        
        # 计算需要的最小区间长度
        need = d - gap + 1
        length = (need + m - 1) // m  # 向上取整
        
        # 检查区间是否在数组范围内
        max_len = n - i  # 从位置i开始的最大可能长度
        if length <= max_len and length >= 1:
            ans = min(ans, length)
    
    return ans if ans != float('inf') else -1

T = int(input())
for _ in range(T):
    print(solve())
  • Cpp
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    
    int T;
    cin >> T;
    
    while (T--) {
        int n;
        ll d, m;
        cin >> n >> d >> m;
        
        vector<ll> a(n);
        for (int i = 0; i < n; i++) {
            cin >> a[i];
        }
        
        // 检查原数组是否已满足条件
        bool found = false;
        for (int i = 1; i < n; i++) {
            if (abs(a[i] - a[i-1]) > d) {
                found = true;
                break;
            }
        }
        
        if (found) {
            cout << 0 << "\n";
            continue;
        }
        
        // 如果单个元素操作就能满足条件
        if (m > d) {
            cout << 1 << "\n";
            continue;
        }
        
        // 枚举所有可能的起始位置
        ll ans = LLONG_MAX;
        for (int i = 1; i < n; i++) {
            ll gap = a[i] - a[i-1];  // 当前相邻差值
            if (gap > d) {  // 已经满足条件
                ans = 0;
                break;
            }
            
            // 计算需要的最小区间长度
            ll need = d - gap + 1;
            ll len = (need + m - 1) / m;  // 向上取整
            
            // 检查区间是否在数组范围内
            ll max_len = n - i;  // 从位置i开始的最大可能长度
            if (len <= max_len && len >= 1) {
                ans = min(ans, len);
            }
        }
        
        cout << (ans == LLONG_MAX ? -1 : ans) << "\n";
    }
    
    return 0;
}
  • Java
import java.util.*;
import java.io.*;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        int T = Integer.parseInt(br.readLine());
        
        while (T-- > 0) {
            String[] line1 = br.readLine().split(" ");
            int n = Integer.parseInt(line1[0]);
            long d = Long.parseLong(line1[1]);
            long m = Long.parseLong(line1[2]);
            
            String[] line2 = br.readLine().split(" ");
            long[] a = new long[n];
            for (int i = 0; i < n; i++) {
                a[i] = Long.parseLong(line2[i]);
            }
            
            // 检查原数组是否已满足条件
            boolean found = false;
            for (int i = 1; i < n; i++) {
                if (Math.abs(a[i] - a[i-1]) > d) {
                    found = true;
                    break;
                }
            }
            
            if (found) {
                System.out.println(0);
                continue;
            }
            
            // 如果单个元素操作就能满足条件
            if (m > d) {
                System.out.println(1);
                continue;
            }
            
            // 枚举所有可能的起始位置
            long ans = Long.MAX_VALUE;
            for (int i = 1; i < n; i++) {
                long gap = a[i] - a[i-1];  // 当前相邻差值
                if (gap > d) {  // 已经满足条件
                    ans = 0;
                    break;
                }
                
                // 计算需要的最小区间长度
                long need = d - gap + 1;
                long length = (need + m - 1) / m;  // 向上取整
                
                /

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

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

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

全部评论

相关推荐

码农索隆:没招完啊,java炒饭可入
点赞 评论 收藏
分享
评论
1
1
分享

创作者周榜

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