蚂蚁笔试 蚂蚁笔试题 0821

笔试时间:2025年8月21日

往年笔试合集:

2023春招秋招笔试合集

2024春招秋招笔试合集

第一题:寻找符合条件的数组

给定一个正整数 n。请你找到一个长度至少为 2 的数组 a,使得数组 a 中仅含 1 和合数,且 a 中所有元素的和为 n。如果有多个满足条件的 a,请输出长度最短的。如果有多个长度最短的 a,你可以输出任意一个。注意,自测运行功能可能因此返回错误结果,请自行检查答案正确性。

输入描述

每个测试文件均包含多组测试数据。第一行输入一个整数 T (1 ≤ T ≤ 10^3) 代表数据组数,每组测试数据描述如下:

输入一行一个正整数 n (2 < n ≤ 10^18)。

输出描述

对于每组测试数据,先输出一行一个正整数 k,表示 a 的长度。在第二行输出 k 个整数,表示 a 中的元素。如果存在多个解法方案,您可以输出任意一个,系统会自动判定是否正确。注意,自测运行功能可能因此返回错误结果,请自行检查答案正确性。

样例输入

3

8

10

2

样例输出

2

4 4

2

1 9

2

1 1

参考题解

当n为偶数时,答案应该是4和n-4; 当n为奇数时,答案应该是1和n-1; 需要暴力特判一下n=2,3,4,6的情况。

C++:

#include <bits/stdc++.h>
using namespace std;

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    long long t; 
    if (!(cin >> t)) return 0;
    while (t--) {
        long long n; 
        cin >> n;
        if (n == 2) {
            cout << "2\n1 1\n";
        } else if (n == 3) {
            cout << "3\n1 1 1\n";
        } else if (n == 4) {
            cout << "4\n1 1 1 1\n";
        } else if (n == 6) {
            cout << "3\n4 1 1\n";
        } else {
            if (n % 2 == 0) {
                cout << "2\n4 " << (n - 4) << "\n";
            } else {
                cout << "2\n" << (n - 1) << " 1\n";
            }
        }
    }
    return 0;
}

Java:

import java.io.*;
import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
        int t = Integer.parseInt(br.readLine().trim());
        for (int _case = 0; _case < t; _case++) {
            long n = Long.parseLong(br.readLine().trim());
            if (n == 2) {
                out.println("2");
                out.println("1 1");
            } else if (n == 3) {
                out.println("3");
                out.println("1 1 1");
            } else if (n == 4) {
                out.println("4");
                out.println("1 1 1 1");
            } else if (n == 6) {
                out.println("3");
                out.println("4 1 1");
            } else {
                if (n % 2 == 0) {
                    out.println("2");
                    out.println("4 " + (n - 4));
                } else {
                    out.println("2");
                    out.println((n - 1) + " 1");
                }
            }
        }
        out.flush();
    }
}

Python:

t = int(input().strip())
res = []
for _ in range(t):
    n = int(input().strip())
    if n == 2:
        print("2\n1 1")
    elif n == 3:
        print("3\n1 1 1")
    elif n == 4:
        print("4\n1 1 1 1")
    elif n == 6:
        print("3\n4 1 1")
    else:
        if n % 2 == 0:
            print(f"2\n4 {n - 4}")
        else:
            print(f"2\n{n - 1} 1")

第二题:文本分类预测

读取数据:输入为JSON格式,包含训练集和测试集:"train": 列表,每个元素为["文本", 标签],其中标签为0或1"test": 列表,仅包含文本预处理

i. 将文本统一转换为小写

ii. 去除首尾空白字符,再用单空格重新连接,消除多余空格特征工程

使用CountVectorizer与TfidfTransformer处理特征:先fit + transform训练集再对测试集仅执行transform模型训练 & 预测在训练集的TF-IDF特征上拟合LogisticRegression对测试集计算正类概率,概率≥0.5则预测为1,否则为0输入描述JSON格式数据,结构如下:

输入描述

JSON格式数据,结构如下:

{

"train": [["文本1", 标签1], ["文本2", 标签2], ...],

"test": ["文本1", "文本2", ...]

}

其中,训练集数据量≥4,每条数据包含文本和标签(0或1);测试集仅包含文本。

输出描述

单行JSON数组,元素为0或1,顺序与测试集文本对应,如[1,0,1]。

样例输入

{"train":[["good movie",1],["great film",1],["bad movie",0],["terible flm",0]],"test":["good film","bad film"]}

样例输出

[1, 0]

参考题解

读取JSON输入数据,分离训练集和测试集。对文本进行预处理:转换为小写,去除首尾空白,用单空格连接消除多余空格。特征工程:使用CountVectorizer将训练集文本转换为词频矩阵,再通过TfidfTransformer转换为TF-IDF特征;对测试集文本执行相同的特征转换(复用训练集的拟合参数)。模型训练:在训练集的TF-IDF特征上拟合LogisticRegression(设置random_state=42)。预测:计算测试集的正类概率,根据≥0.5则为1、否则为0的规则生成预测结果,输出JSON数组。

Python:

import json
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer
from sklearn.linear_model import LogisticRegression
input_data = json.loads(input())
train_data = input_data["train"]
test_texts = input_data["test"]
def preprocess_text(text):
    return" ".join(text.lower().strip().split())
processed_train_texts = [preprocess_text(item[0]) for item in train_data]
train_labels = [int(item[1]) for item in train_data]
processed_test_texts = [preprocess_text(text) for text in test_texts]
count_vectorizer = CountVectorizer()
tfidf_transformer = TfidfTransformer()
train_word_counts = count_vectorizer.fit_transform(processed_train_texts)
train_tfidf = tfidf_transformer.fit_transform(train_word_counts)
log_reg = LogisticRegression(random_state=42)
log_reg.fit(train_tfidf, train_labels)
test_word_counts = count_vectorizer.transform(processed_test_texts)
test_tfidf = tfidf_transformer.transform(test_word_counts)
positive_probs = log_reg.predict_proba(test_tfidf)[:, 1]
predictions = [1if prob >= 0.5else0for prob in positive_probs]
print(json.dumps(predictions))

第三题

TK 有一个长度为 n 的数组 {a1, a2, …, an},其中每个元素 ai 等于 -1 或 1;

你需要与 TK 进行 m 轮游戏,每轮游戏相互独立(即数组的改变并不会影响其他轮次);

在每一轮游戏中,TK 会在当前数组中选择一个区间 [l, r],并记录

  • S = ∑ ai
  • 随后将区间 [l, r] 从数组中删除,剩余元素按原顺序拼接;

你的任务是:在新的数组中找到一个区间 [l1, r1],满足

  • 区间长度与被删除区间相同,即 r1 - l1 = r - l;
  • ∑ ai > S。

如果存在多个满足条件的区间,可以输出任意一个;如果不存在,则输出 -1。

输入描述

每个测试文件均包含多组测试数据:

  • 第一行输入一个整数 T (1 ≤ T ≤ 10),表示测试组数;除此之外,保证单个测试文件的 ∑ n、∑ m 及所有被删除区间长度之和均不超过 10^5;

接下来对于每组测试数据:

  • 第一行输入两个整数 n, m (1 ≤ n, m ≤ 10^5),分别表示数组长度和游戏轮次;
  • 第二行输入 n 个整数 a1, a2, …, an (ai ∈ {-1, 1}),表示初始数组;
  • 此后 m 行,每行输入两个整数 l 和 r (1 ≤ l ≤ r ≤ n),表示 TK 选择的删除区间。

输出描述

对于每组测试数据,输出 m 行,每行对应一轮游戏的答案;如果无解,输出 -1;

否则,输出两个整数 l₁ 和 r₁ (1 ≤ l₁ ≤ r₁ ≤ n - (r - l + 1)),表示你选取的区间。

样例输入

1  

5 2  

-1 1 1 -1 1  

3 4  

1 3  

样例输出

2 3  

-1  

参考题解

说明:第一轮游戏,S = 0,删除后数组变为 {-1, 1, 1},区间 [2, 3] 满足答案。第二轮游戏删除后数组变为 {-1, 1},长度小于 3 一定无解。离线处理:题目中的每轮游戏相互独立,因此我们不必按输入顺序处理。可以将所有查询先读进来,根据一个高效的策略重新排序处理,这种方法叫作“离线”。按长度分组:最有效的策略是按删除区间的长度 k 分组。因为同一长度 k 的所有查询,都需要寻找一个长度也为 k 的新区间,这使得我们可以为每个 k 值进行一次性的预处理,然后快速回答该长度的所有查询。预处理加速:对于一个固定的长度 k,我们可以花 O(n) 时间预处理两样东西:一个数组 Sums_k,Sums_k[i] 存原数组中从 i 开始,长度为 k 的区间的和。基于 Sums_k,再计算出它的前缀最大值和后缀最大值数组。这能让我们在 O(1) 时间内查出任意前缀 [1...i] 或后缀 [j...n] 中的最大区间和及其位置。分情况求解:对于每个查询 (l, r)(长度为 k),最优解只可能来自三种情况:左侧:完全在 l 左边。利用预处理的“前缀最大值”可 O(1) 找到。右侧:完全在 r 右边。利用预处理的“后缀最大值”可 O(1) 找到。跨越:由 l 左侧的后缀和 r 右侧的前缀拼接而成。这部分没有捷径,直接遍历 k-1 种拼接可能,复杂度为 O(k)。

C++:

#include <iostream>
#include <vector>
#include <numeric>
#include <map>
#include <algorithm>

using namespace std;

const int INF = 1e9;

struct Query {
    int id;
    int l, r, k;
};

struct MaxInfo {
    int val;
    int index;

    bool operator>(const MaxInfo& other) const {
        if (val != other.val) {
            return val > other.val;
        }
        return index < other.index; // 优先选下标小的
    }
};

void solve() {
    int n, m;
    cin >> n >> m;
    vector<int> a(n + 1);
    vector<long long> p(n + 1, 0);
    for (int i = 1; i <= n; ++i) {
        cin >> a[i];
        p[i] = p[i - 1] + a[i];
    }

    map<int, vector<Query>> queries_by_len;
    for (int i = 0; i < m; ++i) {
        int l, r;
        cin >> l >> r;
        queries_by_len[r - l + 1].push_back({i, l, r, r - l + 1});
    }

    vector<pair<int, int>> answers(m);

    for (auto const& [k, q_list] : queries_by_len) {
        if (n - k < k) { // 剩余数组长度不足k,无法找到
            for (const auto& q : q_list) {
                answers[q.id] = {-1, -1};
            }
            continue;
        }

        int sums_len = n - k + 1;
        vector<MaxInfo> sums_k(sums_len + 1);
        for (int i = 1; i <= sums_len; ++i) {
            sums_k[i] = {(int)(p[i + k - 1] - p[i - 1]), i};
        }

        vector<MaxInfo> prefix_max(sums_len + 1);
        prefix_max[0] = {-INF, -1};
        for (int i = 1; i <= sums_len; ++i) {
            if (sums_k[i] > prefix_max[i - 1]) {
                prefix_max[i] = sums_k[i];
            } else {
                prefix_max[i] = prefix_max[i - 1];
            }
        }

        vector<MaxInfo> suffix_max(sums_len + 2);
        suffix_max[sums_len + 1] = {-INF, -1};
        for (int i = sums_len; i >= 1; --i) {
            if (sums_k[i] > suffix_max[i + 1]) {
                suffix_max[i] = sums_k[i];
            } else {
                suffix_max[i] = suffix_max[i + 1];
            }
        }

        for (const auto& q : q_list) {
            int S = p[q.r] - p[q.l - 1];
            MaxInfo best_res = {S, -1};
            int best_l1 = -1, best_r1 = -1

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

2025 春招笔试合集 文章被收录于专栏

2025打怪升级记录,大厂笔试合集 C++, Java, Python等多种语言做法集合指南

全部评论

相关推荐

09-02 11:14
已编辑
四川大学 Java
吴offer选手:这种面试是最烦的,学不到东西,然后还被挂的莫名其妙。之前看到一种说法是面试官如果不想要你了,就会问一些很简单的问题,防止你举报他
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

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