【秋招笔试】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 | 选择区间 |
样例1-2 | 无论如何操作都无法使相邻差值超过5,输出-1 |
样例2-1 | 选择区间 |
样例2-2 | 原数组已存在相邻差值 |
样例2-3 | 原数组已存在相邻差值超过10的情况,无需操作,输出0 |
数据范围
题解
这道题的核心思想是分析魔法操作对相邻元素差值的影响。
首先考虑几种特殊情况:
- 如果原数组已经存在相邻差值大于
的情况,那么答案就是
- 如果我们只对一个元素施法(区间长度为1),被修改的元素会增加
,如果
,那么答案就是
对于一般情况,关键观察是:要想产生大的相邻差值,最有效的方法是在区间的左端点制造"跳跃"。
设相邻元素的差值为 (
)。如果我们选择以位置
为左端点、长度为
的区间进行操作,那么操作后:
要使这个差值大于 ,需要满足:
因此,对于每个可能的起始位置 ,我们需要的最小区间长度为:
但是还要考虑区间不能超出数组边界的限制:区间 必须满足
,即
。
最终答案就是所有满足条件的 中的最小值。
算法步骤:
- 检查原数组是否已满足条件
- 检查单个元素操作是否可行
- 枚举每个可能的起始位置,计算所需的最小区间长度
- 返回所有可行方案中的最小长度
时间复杂度:,空间复杂度:
。
参考代码
- 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%内容,订阅专栏后可继续查看/也可单篇购买
互联网刷题笔试宝典,这里涵盖了市面上大部分的笔试题合集,希望助大家春秋招一臂之力