蚂蚁2026.3.19春招笔试真题
- 2026-10-28 16:42:37
今天练习的是蚂蚁算法最新机考笔试题3题。
各大厂真题都整理了近两年的机考题,题库里面有详细思路和答案~
肥猫学长也提供机考辅导助攻和面试辅导欢迎咨询。
微信号:jackwwang8
目前已经整理的题库有如下:如果有需要可以加我微信获取哦
蚂蚁春招题目3.19
第一题:全相等
题目内容
给定一个长度为n、仅由小写字母组成的字符串s(下标从1开始)。定义一个非空子串t是好子串,当且仅当在t中,所有出现过的字符的出现次数两两相等。请你计算字符串s中共有多少个好子串。
名词解释子串:子串为从原字符串中,连续地选择一段字符(可以全选、可以不选)得到的新字符串;
输入描述每个测试文件均包含多组测试数据。第一行输入一个整数T(1 ≤ T ≤ 100)代表数据组数,每组测试数据描述如下:
除此之外,保证单个测试文件的n之和不超过2080。
输出描述对于每一组测试数据,新起一行。输出一个整数,表示满足条件的非空子串的数量。
测试样例
23aab4abab58样例说明
在第一组测试数据中,s="aab",所有子串为(按区间列举):
解题思路
解题思路
核心思路步骤
- 枚举所有子串
:由于字符串长度 n≤2000,枚举所有可能的子串(起点 i,终点 j,1≤i≤j≤n)的时间复杂度是 O (n²)(约 2000²=400 万次),完全在时间限制内; - 统计子串字符频率
:对每个子串,统计其中每个字符的出现次数; - 验证是否为好子串
:提取所有出现过的字符的频率值,检查这些值是否全部相等; - 计数累加
:统计所有满足条件的子串数量。
带详细注释的代码实现
(更加详细解题思路和CPP、Java代码加我微信获取)
(更加详细解题思路和CPP、Java代码加我微信获取)
# 第一题:全相等import sysdef is_good_substring(count_arr): """ 判断当前字符计数数组对应的子串是否为好子串 :param count_arr: 长度为26的列表,记录a-z每个字符的出现次数 :return: 是好子串返回True,否则返回False """ base_count = 0 # 基准出现次数,记录第一个出现字符的次数 for num in count_arr: if num > 0: if base_count == 0: base_count = num # 初始化基准次数 elif num != base_count: return False # 存在字符次数不一致,不是好子串 return True # 所有出现字符次数一致,是好子串def calculate_good_substrings(s): """ 计算字符串中好子串的总数量 :param s: 输入的小写字母字符串 :return: 好子串的数量 """ str_len = len(s) result = 0 # 记录好子串总数 # 枚举所有左端点 for left in range(str_len): char_count = [0] * 26 # 每次左端点更新,重新初始化字符计数数组 # 枚举右端点,从左端点开始向右扩展 for right in range(left, str_len): # 计算当前字符对应的数组下标(a->0, b->1, ..., z->25) char_index = ord(s[right]) - ord('a') char_count[char_index] += 1 # 对应字符计数+1 # 判断当前子串是否为好子串,是则结果+1 if is_good_substring(char_count): result += 1 return resultdef main(): """主函数,处理输入输出并调用核心逻辑""" read_input = sys.stdin.readline # 简化输入读取 test_num = int(read_input().strip()) # 读取测试数据组数 res_list = [] # 存储每组测试数据的结果 for _ in range(test_num): n = int(read_input().strip()) # 读取字符串长度 str_s = read_input().strip() # 读取字符串 # 计算当前组的好子串数量并加入结果列表 res_list.append(str(calculate_good_substrings(str_s))) # 输出所有结果,每组结果占一行 sys.stdout.write("\n".join(res_list))if __name__ == "__main__": main()第二题:文本数值混合特征工程
题目内容
现有一个文本与数值的混合数据,需要你在仅使用numpy/pandas/scikit-learn的前提下,实现下表所示四段式特征工程+双基模型平均流程,并输出测试集标签。
核心流程要求
输入描述输入为一行JSON格式数据,包含train_txt(训练集文本)、train_num(训练集数值特征)、train_y(训练集标签)、test_txt(测试集文本)、test_num(测试集数值特征)。
输出描述仅一行:[pred_1,pred_2,...,pred_n],长度等于测试集数量的JSON整数数组(0/1),以空格间隔。
补充说明
测试样例
{"train_txt": ["great food and service", "fantastic taste", "delicious pizza", "awesome restaurant"], "train_num": [[1,2],[3,4],[5,6],[7,8]], "train_y": [1,1,0,0], "test_txt": ["bad food", "good taste"], "test_num": [[2,3],[4,5]]}[0, 1]样例说明
输入包含4条训练数据、2条测试数据,经特征工程和双模型平均预测后,测试集第一条标签为0,第二条标签为1,故输出[0, 1]。
解题思路
核心步骤
- 文本特征提取
: 词级 TF-IDF:使用指定参数的 TfidfVectorizer处理文本,提取 1-2 元词特征;字符 3-gram TF-IDF:使用字符级分析器,提取 3 元字符特征; - 数值特征处理
: 标准化:对数值特征用 StandardScaler做 Z-score 标准化;二次多项展开:对标准化后的数值特征做 2 次多项式展开(不含偏置项); - 特征合并
:将词级 TF-IDF、字符 3-gram TF-IDF、处理后的数值特征横向拼接为稀疏矩阵; - 模型训练与预测
: 训练 LogisticRegression 和 SGDClassifier 两个模型; 分别输出测试集正类概率,取平均值后按 0.5 阈值生成最终标签。
带详细注释的代码实现(更加详细解题思路和CPP、Java代码加我微信获取)
(更加详细解题思路和CPP、Java代码加我微信获取)
# 第二题:文本数值混合特征工程import sysfrom ast import literal_evalfrom scipy.sparse import hstack, csr_matrixfrom sklearn.feature_extraction.text import TfidfVectorizerfrom sklearn.preprocessing import StandardScaler, PolynomialFeaturesfrom sklearn.linear_model import LogisticRegression, SGDClassifierdef process_feature_and_predict(data): """ 按要求完成特征工程、模型训练和预测 :param data: 解析后的字典,包含训练和测试的文本、数值、标签数据 :return: 测试集的预测标签列表 """ # 从输入数据中提取训练和测试集的各个部分 train_text = data["train_txt"] train_numeric = data["train_num"] train_label = data["train_y"] test_text = data["test_txt"] test_numeric = data["test_num"] # 1. 构建词级TF-IDF特征 word_tfidf = TfidfVectorizer( lowercase=True, stop_words="english", ngram_range=(1, 2), sublinear_tf=True ) train_word_feat = word_tfidf.fit_transform(train_text) # 训练集拟合并转换 test_word_feat = word_tfidf.transform(test_text) # 测试集仅转换 # 2. 构建字符3-gram TF-IDF特征 char_tfidf = TfidfVectorizer( analyzer="char", ngram_range=(3, 3), lowercase=True, sublinear_tf=True ) train_char_feat = char_tfidf.fit_transform(train_text) # 训练集拟合并转换 test_char_feat = char_tfidf.transform(test_text) # 测试集仅转换 # 3. 处理数值特征:标准化 + 二次多项式展开 scaler = StandardScaler() # 初始化标准化器 poly = PolynomialFeatures(degree=2, include_bias=False) # 初始化多项式展开器 train_num_std = scaler.fit_transform(train_numeric) # 训练集数值特征标准化 test_num_std = scaler.transform(test_numeric) # 测试集数值特征标准化 train_num_poly = poly.fit_transform(train_num_std) # 训练集标准化后多项式展开 test_num_poly = poly.transform(test_num_std) # 测试集标准化后多项式展开 # 将数值特征转为稀疏矩阵,方便与TF-IDF稀疏特征拼接 train_num_sparse = csr_matrix(train_num_poly) test_num_sparse = csr_matrix(test_num_poly) # 4. 特征合并:横向拼接词级、字符级、数值特征 train_total_feat = hstack([train_word_feat, train_char_feat, train_num_sparse]) test_total_feat = hstack([test_word_feat, test_char_feat, test_num_sparse]) # 5. 训练模型A:逻辑回归 model_log = LogisticRegression( penalty="l2", C=1.0, solver="liblinear", max_iter=1000, random_state=42 ) model_log.fit(train_total_feat, train_label) # 6. 训练模型B:随机梯度下降分类器(逻辑损失) model_sgd = SGDClassifier( loss="log_loss", penalty="l2", alpha=1e-4, max_iter=1000, random_state=42 ) model_sgd.fit(train_total_feat, train_label) # 7. 软投票:获取两个模型的正类概率并取平均 prob_log = model_log.predict_proba(test_total_feat)[:, 1] # 模型A正类概率 prob_sgd = model_sgd.predict_proba(test_total_feat)[:, 1] # 模型B正类概率 avg_prob = (prob_log + prob_sgd) / 2.0 # 概率平均值 # 根据阈值0.5生成最终预测标签 predict_label = [1 if p > 0.5 else 0 for p in avg_prob] return predict_labeldef main(): """主函数,处理输入解析和结果输出""" # 读取整行输入并解析为字典 input_str = sys.stdin.read().strip() input_data = literal_eval(input_str) # 调用核心函数得到预测结果 pred_result = process_feature_and_predict(input_data) # 按要求格式输出结果 print("[" + ", ".join(map(str, pred_result)) + "]")if __name__ == "__main__": main()第三题:四元异或
题目内容
给定一个长度为n的整数数组a1,a2,...,an与整数k,请判断是否存在四个两两不同的下标i,j,p,q(即i,j,p,q互不相同),使得ai XOR aj XOR ap XOR aq = k。若存在输出Yes,否则输出No。
名词解释按位异或(记作XOR):对每一位二进制独立计算,相同为0,不同为1。两两不同:四个下标互不相同,不可复用同一位置的元素。
输入描述每个测试文件均包含多组测试数据。第一行输入一个整数T(1 ≤ T ≤ 1000)代表数据组数,每组测试数据描述如下:
所有测试中n的总和≤4000。
输出描述输出T行,若存在满足条件的四元组,输出Yes;否则输出No。
测试样例
34 41 2 3 45 01 2 4 8 164 71 2 3 7YesNoYes样例说明
解题思路
解题思路
核心优化思路
利用异或的性质:a XOR b XOR c XOR d = k → a XOR b XOR c = k XOR d。将四元组拆解为前三个数的异或和第四个数与 k 的异或的匹配问题,步骤如下:
预处理所有「三元组(i,j,p)的异或值 + 对应的下标集合」,存储到字典中(键:异或值,值:下标集合列表); 遍历每个下标 q,计算 target = k XOR a[q];检查字典中是否存在 target对应的三元组下标集合,且该集合与 q 无交集(保证四个下标互不相同);若存在则输出 Yes,否则遍历结束后输出 No。
复杂度分析
预处理三元组:O (n³),但 n≤1000 时 n³=10⁹,看似超时,但实际测试中 n 总和≤4000,且大部分用例 n 较小,结合提前终止(找到符合条件的就返回),可以通过; 进一步优化:可先枚举二元组(i,j)的异或值,存储 {异或值: [(i,j)]},再枚举(p,q)计算target = k XOR a[p] XOR a[q],检查是否存在 (i,j) 与 (p,q) 无交集,时间复杂度降为 O (n²),更高效。
带详细注释的代码实现(更加详细解题思路和CPP、Java代码加我微信获取)
(更加详细解题思路和CPP、Java代码加我微信获取)
(更加详细解题思路和CPP、Java代码加我微信获取)
# 第三题:四元异或import sysdef check_four_xor(nums, target_k): """ 判断数组中是否存在四个下标互不相同的数,异或和等于target_k :param nums: 输入的整数数组 :param target_k: 目标异或和 :return: 存在返回True,否则返回False """ arr_len = len(nums) xor_set = set() # 存储前缀数对的异或值,保证与当前数对下标不重合 # 枚举当前数对的左端点i,范围1到n-2(保证j有足够范围) for i in range(1, arr_len - 1): # 枚举当前数对的右端点j,j > i for j in range(i + 1, arr_len): current_xor = nums[i] ^ nums[j] # 计算当前数对的异或值 need_xor = target_k ^ current_xor # 计算需要的前缀异或值 if need_xor in xor_set: return True # 找到符合条件的四元组,直接返回True # 将所有p < i的数对(p, i)的异或值加入集合,供后续数对匹配 for p in range(i): xor_set.add(nums[p] ^ nums[i]) # 遍历结束未找到符合条件的四元组 return Falsedef main(): """主函数,处理批量输入并调用核心判断逻辑""" # 读取所有输入并转换为整数列表,适合大批次输入处理 all_data = list(map(int, sys.stdin.buffer.read().split())) data_index = 0 test_count = all_data[data_index] # 读取测试组数 data_index += 1 result_list = [] # 存储每组测试的结果(Yes/No) for _ in range(test_count): n = all_data[data_index] # 读取数组长度 k = all_data[data_index + 1] # 读取目标异或和 data_index += 2 num_array = all_data[data_index:data_index + n] # 读取当前数组 data_index += n # 判断并将结果加入列表 if check_four_xor(num_array, k): result_list.append("Yes") else: result_list.append("No") # 输出所有结果,每组结果占一行 sys.stdout.write("\n".join(result_list))if __name__ == "__main__": main()扫描它,然后带走我:
微信号| jackwwang8
bilibili| 养只猫一米哒
小红书| 2878931801