蚂蚁笔试 蚂蚁笔试题 0508
笔试时间:2025年5月8日
往年笔试合集:
第一题:Y串
对于给定的字符串 S1S2…Sn,将其全部奇数位置的字符删除,得到新的字符串 S′,随后将 S′ 反转,得到新的字符串 S′′,最后,将 S′′中的所有小写字母转换为大写字母。
你需要输出最终得到的字符串 S′′。
输入描述
第一行输入一个长度为 1≤len(S)≤105,由大小写字母混合构成的字符串 S。
输出描述
输出最终得到的字符串 S′′。
样例输入
WhilE
样例输出
LH
第一步,删除奇数位置的字符,得到新的字符串S'="hl";
第二步,反转字符串,得到新的字符串S''="lh";
第三步,将S''中的所有小写字母转换为大写字母,得到最终的字符里S''="LH"
参考题解
签到题,模拟即可。先删除奇数位置,得到新字符串,之后将其反转,最后小写转大写即可。
C++:
#include<bits/stdc++.h> usingnamespacestd; int main() { string s; cin >> s; string t; for (int i = 1; i < s.length(); i += 2) { t += s[i]; } reverse(t.begin(), t.end()); for (char& c : t) { if (islower(c)) { c = toupper(c); } } cout << t; }
Java:
import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); String s = sc.next(); StringBuilder t = new StringBuilder(); // 提取每隔一个字符 for (int i = 1; i < s.length(); i += 2) { t.append(s.charAt(i)); } // 反转字符串 t.reverse(); // 转换小写字母为大写 for (int i = 0; i < t.length(); i++) { if (Character.isLowerCase(t.charAt(i))) { t.setCharAt(i, Character.toUpperCase(t.charAt(i))); } } System.out.println(t); } }
Python:
def main(): s = input() t = '' # 提取每隔一个字符 for i in range(1, len(s), 2): t += s[i] # 反转字符串 t = t[::-1] # 转换小写字母为大写 t = ''.join([char.upper() if char.islower() else char for char in t]) print(t) if __name__ == "__main__": main()
第二题:小红的查询线段
小红有一根长度为 n 的绳子,她在绳子上均匀地画了 n 个点(包括端点),点的编号为 1 ~ n,这样绳子被均分为 n 段。
她现在提出 Q 次查询,每次查询要进行下列操作的其中一种:
操作一:在点 a (1 ≤ a ≤ n) 上画一条红线。
操作二:若把当前画红线的地方全部删掉,询问是否存在长度大于等于 k 的绳子。
不考虑绳子损坏且每次询问都是独立(即假设绳子断裂,但实际上并不是真的断裂),请你回答小红的每次询问。
输入描述
第一行输入两个整数 n, Q (3 ≤ n ≤ 10^9; 1 ≤ Q ≤ 10^5) 代表绳子的长度,小红的操作查询次数。
接下来 Q 行,每行先输入一个整数 op (1 ≤ op ≤ 2) 表示操作查询的类型,随后:
当 op = 1,在后续一行输入一个整数 a (1 ≤ a ≤ n),表示在 x 处画一条红线。
当 op = 2,在后续一行输入一个整数 k (1 ≤ k ≤ 10^9) 查询若把当前的红线断开,是否存在长度大于等于 k 的绳子的长度。
输出描述
对于每个询问二,若把当前的红线剪断,会存在长度大于等于k的绳子,在一行上输出YES ;否则,直接输出NO。
样例输入
8 7
2 7
1 4
2 4
2 5
1 6
2 3
2 4
样例输出
YES
YES
NO
YES
NO
初始时绳子形象的表示为1-2-3-4-5-6-7-8;
对于第一次操作,由于此前没有画过红线,所以得到一根长度为7的绳子,符合询问;
对于第二次操作,在第四个点的位置画一条红线,得到1-2-3-[4]-5-6-7-8;
对于第三次操作,切断后得到一根长度为3的绳子和一很长度为4的绳子,1-2-3-4和4-5-6-7-8,符合询问;
对于第四次操作,同上,不符合询问:
对于第五次操作,在第六个点的位置画一条红线,得到1-2-3-[4]-5-[6]-7-8;
对于第六次操作,切断后得到一根长度为3的绳子和两根长度为2的绳子,1-2-3-4、4-5-6和6-7-8,符合询问。
参考题解
set+map,利用set维护所有红线的位置,利用map维护每种长度绳子出现的数量。对于操作一,在x处画一条红线,假如x已在set中,说明之前画过红线则跳过。否则在set中二分小于x且最大的红线位置记作lc,大于x且最小的红线记作rc。那么原来的长度rc-lc会被切断成x-lc和rc-x两段,在map中更新对应数量。对于操作二,直接看map中最大的那个长度是否大于等于k即可。
C++:
#include <bits/stdc++.h> usingnamespacestd; int main() { int n, q; cin >> n >> q; set<int> st; map<int, int> mp; mp[n - 1] = 1; while (q--) { int op; cin >> op; if (op == 1) { int x; cin >> x; x--; if (st.find(x) != st.end()) { continue; } int lc = 0; auto it_lc = st.upper_bound(x); if (it_lc != st.begin()) { --it_lc; lc = *it_lc; } int rc = n - 1; auto it_rc = st.upper_bound(x); if (it_rc != st.end()) { rc = *it_rc; } int sz = rc - lc; auto map_it = mp.find(sz); if (map_it != mp.end()) { if (--map_it->second == 0) { mp.erase(map_it); } } mp[x - lc]++; mp[rc - x]++; st.insert(x); } else { int k; cin >> k; if (mp.empty() || mp.rbegin()->first < k) { cout << "NO\n"; } else { cout << "YES\n"; } } } }
Java:
import java.util.*; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int n = sc.nextInt(); int q = sc.nextInt(); Set<Integer> st = new TreeSet<>(); Map<Integer, Integer> mp = new HashMap<>(); mp.put(n - 1, 1); while (q-- > 0) { int op = sc.nextInt(); if (op == 1) { int x = sc.nextInt(); x--; // 如果 x 已经存在,则跳过 if (st.contains(x)) { continue; } int lc = 0;
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
2025打怪升级记录,大厂笔试合集 C++, Java, Python等多种语言做法集合指南