【春招笔试】2025.03.30-蚂蚁算法岗改编题
✅ 春招备战指南 ✅
💡 学习建议:
- 先尝试独立解题(建议用时:90分钟/套)
- 对照解析查漏补缺
- 配套练习题库
🧸 题面描述背景等均已深度改编,做法和题目本质基本保持一致。
🍹 感谢各位朋友们的订阅,你们的支持是我们创作的最大动力
春秋招合集 -> 互联网必备刷题宝典🔗
题目一:复制粘贴的艺术
1️⃣:通过枚举复制的位置,找到最优解
2️⃣:检查目标字符串前缀是否可以通过复制粘贴操作得到
3️⃣:根据具体情况计算最少操作次数
难度:中等
这道题目的关键在于发现可能的复制粘贴模式。当我们使用复制粘贴时,必须确保前k个字符等于接下来的k个字符。通过枚举可能的k值并计算相应的操作次数,我们可以找到最优解,算法复杂度为O(n²)。
题目二:网购行为分析系统
1️⃣:对用户行为数据进行最大最小归一化处理
2️⃣:使用特定公式计算用户行为得分
3️⃣:处理特殊情况并格式化输出结果
难度:中等
这道题目结合了数据处理和数学公式计算,要求对用户行为数据进行归一化处理并计算得分。关键是理解最大最小归一化的概念,正确处理边界情况,并按照指定格式输出结果。算法复杂度为O(n),其中n是用户数量。
题目三:字符串最大化连续字符
1️⃣:枚举保留的目标字符
2️⃣:使用双指针技术计算可能的最长连续序列
3️⃣:通过删除非目标字符,最大化连续字符长度
难度:中等
这道题目要求通过删除恰好k个字符,使剩余字符串的连续度最大。核心思路是枚举每种字符作为保留目标,使用双指针方法找出可以形成的最长连续序列。算法复杂度为O(26n),即O(n),其中n是字符串长度。
01. 复制粘贴的艺术
问题描述
A小姐最近在学习一款文本编辑器,她发现这款编辑器有两种特殊操作:
- 在文本末尾添加任意一个字符。
- 复制整个当前文本,然后将复制的内容粘贴到文本末尾。
A小姐很好奇,如果她一开始拥有一个空白文档,那么最少需要多少次操作才能得到她想要的目标文本呢?需要注意的是,复制粘贴这个操作在整个过程中最多只能使用一次。
输入格式
输入一个字符串 ,表示A小姐想要得到的目标文本,长度不超过
。
输出格式
输出一个整数,表示最少需要的操作次数。
样例输入
ababababc
样例输出
6
数据范围
ababababc | 首先添加4个字符得到"abab",然后使用复制粘贴操作得到"abababab",最后添加字符'c',总共需要4+1+1=6次操作 |
题解
这道题目乍看之下可能有点复杂,但其实我们可以通过分析操作的特性来找出规律。
首先,如果我们不使用复制粘贴操作,那么我们需要的操作次数就等于目标字符串的长度,因为我们需要一个一个地添加每个字符。
但如果我们使用复制粘贴操作,就可能减少总的操作次数。关键是要找出复制粘贴的最佳时机。
想象一下,假设我们已经构建了前 个字符,然后使用了复制粘贴操作,那么我们会得到这
个字符的重复,即总共
个字符。为了使这个操作有效,这
个字符必须是目标字符串的前
个字符的一部分,也就是说前
个字符必须等于接下来的
个字符。
所以,我们可以枚举所有可能的 值(从1到
),检查是否满足
。如果满足,那么我们可以通过以下步骤构建目标字符串:
- 添加前
个字符,需要
次操作
- 使用一次复制粘贴操作,得到
个字符
- 继续添加剩余的
个字符
总操作次数为 。
我们需要找出使得这个表达式最小的 值,即使得
尽可能大的值。但记住,
必须满足
。
时间复杂度分析:我们枚举 的值,对于每个
,需要比较两个长度为
的子串,这需要
的时间。总的时间复杂度为
,其中
是目标字符串的长度。考虑到
最大为1000,这个算法是足够高效的。
参考代码
- Python
import sys
input = lambda:sys.stdin.readline().strip()
# 获取目标字符串
s = input()
n = len(s)
# 默认答案为不使用复制粘贴的情况
ans = n
# 枚举可能的复制长度
for k in range(1, n // 2 + 1):
# 检查前k个字符是否等于接下来的k个字符
if s[:k] == s[k:2*k]:
# 计算总操作次数:k次添加 + 1次复制粘贴 + (n-2k)次添加剩余字符
ops = k + 1 + (n - 2 * k)
ans = min(ans, ops)
print(ans)
- Cpp
#include <iostream>
#include <string>
using namespace std;
int main() {
string s;
cin >> s;
int n = s.size();
// 默认答案为字符串长度
int ans = n;
// 枚举复制长度k
for (int k = 1; k <= n/2; k++) {
// 判断前k个字符是否等于接下来的k个字符
if (s.substr(0, k) == s.substr(k, k)) {
// 计算操作次数
int tmp = k + 1 + (n - 2*k);
ans = min(ans, tmp);
}
}
cout << ans << endl;
return 0;
}
- Java
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
int n = s.length();
// 默认答案为字符串长度
int ans = n;
// 枚举可能的复制长度
for (int k = 1; k <= n/2; k++) {
// 检查是否满足复制条件
if (s.substring(0, k).equals(s.substring(k, 2*k))) {
// 计算操作次数
int ops = k + 1 + (n - 2*k);
ans = Math.min(ans, ops);
}
}
System.out.println(ans);
sc.close();
}
}
02. 网购行为分析系统
问题描述
小柯是一家大型电商平台的数据分析师,她需要设计一个系统来评估用户的购物行为,以便为用户提供更个性化的推荐服务。经过调研,她发现用户的行为主要可以通过三个指标来量化:点击次数(clicks)、浏览时间(duration)和购买次数(purchases)。
为了更科学地评估用户行为,小柯设计了一个行为得分计算公式,需要先对这三个指标进行归一化处理,然后根据特定的公式计算最终得分。
你的任务是帮助小柯实现这个评分系统,根据输入的用户行为数据计算每个用户的行为得分。
输入格式
输入是一个字典,键是用户的 (字符串),值是一个字典,包含 "
"、"
"、"
" 三个键,分别代表用户的点击次数、停留时间、购买次数(均为整数)。
输出格式
返回一个字典,格式与输入相同,但是输出每个用户的行为得分。
样例输入
{"user1":{"clicks":10,"duration":3600,"purchases":2},"user2":{"clicks":20,"duration":7200,"purchases":1},"user3":{"clicks":30,"duration":10800,"purchases":0}}
样例输出
{user1":{"score":2.0},"user2":{"score":2.429},"user3":{"score":3.411}}
数据范围
- 用户数量范围:
- 点击次数范围:
- 浏览时间范围:
(单位:秒)
- 购买次数范围:
样例1 | 首先对所有用户的三个指标进行最大最小归一化,然后根据公式 |
题解
这道题目看起来有点复杂,但其实思路很清晰,主要分为两个步骤:数据归一化和得分计算。
首先,什么是最大最小归一化?简单来说,就是将数据线性变换到[0,1]区间内,变换公式为:
特别地,当所有值都相等时(即最大值=最小值),归一化结果就是0。
对于本题,我们需要对每个特征(clicks、duration、purchases)分别进行归一化处理。具体步骤如下:
- 读取输入数据并解析为字典格式
- 收集所有用户的三个特征值,找出每个特征的最大值和最小值
- 使用最大最小归一化公式,计算每个用户每个特征的归一化值
- 根据给定的公式计算得分:
- 将结果四舍五入保留至多3位小数
需要注意的是,题目还有一个特殊情况:当所有用户的clicks、duration和purchases都为0时,应该返回"NaN"作为得分。这是因为在这种情况下,我们无法进行有意义的归一化和比较。
关于计算公式的设计,它综合考虑了三个特征的不同影响:
- 对点击次数使用对数函数,可以降低高点击量的权重,使得评分不会因极端值而失真
- 对浏览时间使用指数函数,可以强调长时间浏览的重要性
- 对购买次数使用二次项,表明购买行为是最有价值的指标
时间复杂度分析:我们需要遍历所有用户两次,一次是为了找出特征的最大最小值,另一次是为了计算得分。因此总体时间复杂度为O(n),其中n是用户数量。考虑到用户数最多为1000,这个算法效率很高。
参考代码
- Python
import sys
input = lambda:sys.stdin.readline().strip()
import json
import math
# 从终端读取输入
input_str = input()
data = json.loads(input_str)
# 检查是否所有数据都为0
all_zero = True
for user, info in data.items():
if info['clicks'] > 0 or info['duration'] > 0 or info['purchases'] > 0:
all_zero = False
break
# 如果全为0则返回NaN
if all_zero:
res = {user: {"score": "NaN"} for user in data}
print(json.dumps(res))
exit()
# 提取各特征的值列表
clk = [info['clicks'] for info in data.values()]
dur = [info['duration'] for info in data.values()]
pur = [info['purchases'] for info in data.values()]
# 计算最大最小值
min_c, max_c = min(clk), max(clk)
min_d, max_d = min(dur), max(dur)
min_p, max_p = min(pur), max(pur)
# 计算每个用户的得分
result = {}
for uid, info in data.items():
# 归一化处理
nc = 0 if max_c == min_c else (info['clicks'] - min_c) / (max_c - min_c)
nd = 0 if max_d == min_d else (info['duration'] - min_d) / (max_d - min_d)
np = 0 if max_p == min_p else (info['purchases'] - min_p) / (max_p - min_p)
# 按公式计算得分
scr = math.log(1 + nc) + math.exp(nd) + np * (np + 1) / 2
result[uid] = {"score": round(scr, 3)}
# 输出结果
print(json.dumps(result))
- Cpp
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <cmath>
#include <algorithm>
#include <iomanip>
using namespace std;
int main() {
// 注意:真实环境中需要正确解析JSON,这里简化处理
string json_str;
getline(cin, json_str);
// 假设我们已经解析出了用户数据
map<string, map<string, int>> data = {
{"user1", {{"clicks", 10}, {"duration", 3600}, {"purchases", 2}}},
{"user2", {{"clicks", 20}, {"duration", 7200}, {"purchases", 1}}},
{"user3", {{"clicks", 30}, {"duration", 10800}, {"purchases", 0}}}
};
// 检查是否所有值都为0
bool all_zero = true;
for (auto& [uid, vals] : data) {
if (vals["clicks"] > 0 || vals["dura
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
互联网刷题笔试宝典,这里涵盖了市面上大部分的笔试题合集,希望助大家春秋招一臂之力