🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员
✨ 本系计划跟新各公司春秋招的笔试题
💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导
👏 感谢大家的订阅➕ 和 喜欢💗
📧 清隆这边最近正在收集近一年互联网各厂的笔试题汇总,如果有需要的小伙伴可以关注CSDN同名公主号领取,会在飞书进行同步的跟新。
文章目录
- 📖 写在前面
- 夏天要来了 秋招还会远吗?
- 🍄 01.卢小姐的蛋糕分享
- 问题描述
- 输入格式
- 输出格式
- 样例输入
- 样例输出
- 数据范围
- 题解
- 参考代码
- 🎧 02.字符串的魔法变换
- 问题描述
- 输入格式
- 输出格式
- 样例输入
- 样例输出
- 数据范围
- 题解
- 参考代码
- 🍿 03.LYA 的魔法项链
- 问题描述
- 输入格式
- 输出格式
- 样例输入
- 样例输出
- 数据范围
- 题解
- 参考代码
- 🎀 写在最后
- 🛖 这里介绍一下咱们的笔试打卡小屋
- 🥰 打卡奖励
- 🕰 每日学习安排
- 📖 打卡小屋涉及题型
- 基础算法
- 基础数据结构
- 搜索
- 动态规划 & 贪心 & 数论
📖 写在前面
夏天要来了 秋招还会远吗?
前不久春招也算是圆满结束咯,大家有拿到心仪的 offer吗?
接下来互联网的秋招也快来啦,小伙伴们有开始准备了吗?
本次给大家带来24届秋招 阿里系 的笔试题目三语言解析(Java/Python/Cpp)
文末有清隆学长的笔试陪伴打卡小屋活动介绍:
✨丰富的打卡奖励等你来领哦,大厂笔试题汇总,笔试面试经验贴,算法笔试模版…
💽 有兴趣的小伙伴们也可以了解一下,不要错过啦~
🍄 01.卢小姐的蛋糕分享
问题描述
卢小姐今天烤了一个蛋糕,打算和朋友们一起分享。蛋糕被切成了 B B B 块,卢小姐自己先拿走了 A A A 块。现在,卢小姐想知道,剩下的蛋糕占整个蛋糕的比例是多少。
换句话说,给定两个正整数 A A A 和 B B B,请计算 1 − A B 1 - \frac{A}{B} 1−BA 的值,并以分数的形式输出,分子和分母之间用空格隔开。
输入格式
输入一行,包含两个正整数 A A A 和 B B B,表示卢小姐拿走的蛋糕块数和蛋糕总块数,数据之间用空格隔开。
输出格式
输出一行,包含两个整数,表示 1 − A B 1 - \frac{A}{B} 1−BA 的值,分子和分母之间用空格隔开。注意,输出的分母必须为 B B B。
样例输入
6 11
样例输出
5 11
数据范围
1 ≤ A < B ≤ 1 0 3 1 \le A < B \le 10^3 1≤A<B≤103
题解
根据题目要求,我们需要计算 1 − A B 1 - \frac{A}{B} 1−BA 的值,并以分数形式输出。我们可以通过以下步骤求解:
- 将 1 1 1 转化为 B B \frac{B}{B} BB 的形式。
- 计算 B B − A B \frac{B}{B} - \frac{A}{B} BB−BA,得到 B − A B \frac{B-A}{B} BB−A。
- 输出 B − A B-A B−A 和 B B B,即为所求分数的分子和分母。
时间复杂度:
O
(
1
)
O(1)
O(1)。
空间复杂度:
O
(
1
)
O(1)
O(1)。
参考代码
- Python
a, b = map(int, input().split())
print(b - a, b)
- Java
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int a = sc.nextInt();
int b = sc.nextInt();
System.out.println((b - a) + " " + b);
}
}
- Cpp
#include <iostream>
using namespace std;
int main() {
int a, b;
cin >> a >> b;
cout << b - a << " " << b << endl;
return 0;
}
🎧 02.字符串的魔法变换
问题描述
LYA 是一个喜欢研究字符串的女孩。她发现,如果将一个字符串
S
S
S 中的某一段子串
S
[
L
,
R
]
S[L,R]
S[L,R] 进行翻转,可以得到一个新的字符串。例如,将字符串 abcdefg
的子串 cdef
进行翻转,可以得到新字符串 abfedcg
。
现在,LYA 有两个长度均为 n n n 的字符串 A A A 和 B B B,她想知道是否可以通过对字符串 A A A 执行 恰好一次 上述的子串翻转操作,使其变成字符串 B B B。如果可以,请求出有多少种不同的翻转方案。
输入格式
第一行包含一个正整数 n n n,表示字符串的长度。
第二行包含一个长度为 n n n 的字符串 A A A。
第三行包含一个长度为 n n n 的字符串 B B B。
输出格式
输出一个整数,表示将字符串 A A A 变成字符串 B B B 的不同翻转方案数。如果无法通过一次翻转实现,则输出 0 0 0。
样例输入
6
abcdef
afedcb
样例输出
1
数据范围
- 1 ≤ n ≤ 1 0 4 1 \le n \le 10^4 1≤n≤104
- 字符串 A A A 和 B B B 仅包含小写字母
题解
本题可以通过双指针来解决。
首先,我们可以从字符串 A A A 和 B B B 的左右两端开始比较,找到第一个不同的字符位置 l l l 和最后一个不同的字符位置 r r r。如果 A [ l , r ] A[l,r] A[l,r] 翻转后与 B [ l , r ] B[l,r] B[l,r] 相同,那么就有可能通过一次翻转实现从 A A A 到 B B B 的转换。
接下来,我们验证 A [ l , r ] A[l,r] A[l,r] 翻转后是否与 B [ l , r ] B[l,r] B[l,r] 完全相同。如果不同,说明无法通过一次翻转实现转换,输出 0 0 0。
如果 A [ l , r ] A[l,r] A[l,r] 翻转后与 B [ l , r ] B[l,r] B[l,r] 相同,我们就找到了一种翻转方案。然后,我们可以尝试扩展这个翻转区间,将 l l l 向左移动, r r r 向右移动,并比较 A [ l ] A[l] A[l] 和 A [ r ] A[r] A[r] 是否相等。如果相等,那么这也是一种合法的翻转方案,翻转区间可以继续扩展。直到 l l l 和 r r r 到达字符串边界或者 A [ l ] ≠ A [ r ] A[l] \ne A[r] A[l]=A[r] 时,扩展停止。
最后,输出累计的翻转方案数即可。
时间复杂度 O ( n ) O(n) O(n),空间复杂度 O ( 1 ) O(1) O(1)。
参考代码
- Python
def solve(n, a, b):
l = 0
r = n - 1
while l < n and a[l] == b[l]:
l += 1
while r >= 0 and a[r] == b[r]:
r -= 1
if l > r:
return 1
left, right = l, r
while left <= r:
if a[left] != b[right]:
return 0
left += 1
right -= 1
ans = 1
l -= 1
r += 1
while l >= 0 and r < n:
if a[l] == a[r]:
ans += 1
l -= 1
r += 1
else:
break
return ans
n = int(input())
a = input()
b = input()
print(solve(n, a, b))
- Java
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
String a = sc.next();
String b = sc.next();
System.out.println(solve(n, a, b));
}
private static int solve(int n, String a, String b) {
int l = 0;
int r = n - 1;
while (l < n && a.charAt(l) == b.charAt(l)) {
l++;
}
while (r >= 0 && a.charAt(r) == b.charAt(r)) {
r--;
}
if (l > r) {
return 1;
}
int left = l;
int right = r;
while (left <= r) {
if (a.charAt(left) != b.charAt(right)) {
return 0;
}
left++;
right--;
}
int ans = 1;
l--;
r++;
while (l >= 0 && r < n) {
if (a.charAt(l) == a.charAt(r)) {
ans++;
l--;
r++;
} else {
break;
}
}
return ans;
}
}
- Cpp
#include <iostream>
#include <string>
using namespace std;
int solve(int n, string a, string b) {
int l = 0;
int r = n - 1;
while (l < n && a[l] == b[l]) {
l++;
}
while (r >= 0 && a[r] == b[r]) {
r--;
}
if (l > r) {
return 1;
}
int left = l;
int right = r;
while (left <= r) {
if (a[left] != b[right]) {
return 0;
}
left++;
right--;
}
int ans = 1;
l--;
r++;
while (l >= 0 && r < n) {
if (a[l] == a[r]) {
ans++;
l--;
r++;
} else {
break;
}
}
return ans;
}
int main() {
int n;
string a, b;
cin >> n >> a >> b;
cout << solve(n, a, b) << endl;
return 0;
}
🍿 03.LYA 的魔法项链
问题描述
LYA 是一位热爱魔法的少女。她拥有一条由 n n n 颗宝石组成的魔法项链,每颗宝石都有自己的颜色。然而,这条项链的魔力只有在所有宝石颜色相同时才能释放。
为了激活项链的魔力,LYA 可以使用魔法来移除项链上的一些宝石。每次移除操作需要选择项链上若干个位置不相邻的宝石进行移除。LYA 希望在项链变得只有一种颜色的宝石时,所需的移除操作次数最少。
现在,LYA 想知道,对于给定的项链长度 n n n 和移除操作次数 k k k,有多少种可能的初始项链状态。由于答案可能很大,请帮助 LYA 构造任意一种满足条件的初始项链状态。
输入格式
输入一行,包含两个以空格分隔的正整数 n n n 和 k k k,分别表示项链的长度和移除操作的次数。
输出格式
输出一个长度为 n n n 的字符串,仅由小写字母构成,表示一种满足条件的初始项链状态。如果不存在满足条件的项链状态,则输出 − 1 -1 −1。
样例输入
6 2
样例输出
abcabc
数据范围
- 1 ≤ k ≤ n ≤ 2 × 1 0 5 1 \leq k \leq n \leq 2 \times 10^5 1≤k≤n≤2×105
题解
这道题可以通过构造的方法来解决。我们可以先确定最终项链的颜色,然后在初始项链中添加一些其他颜色的宝石,使得移除操作的次数恰好等于 k k k。
具体步骤如下:
-
计算需要移除的宝石数量 d e l e t e C o u n t = 2 k − 1 deleteCount = 2^{k-1} deleteCount=2k−1。
-
计算最终剩余的宝石数量 s u r v i v o r C o u n t = n − d e l e t e C o u n t survivorCount = n - deleteCount survivorCount=n−deleteCount。如果 s u r v i v o r C o u n t < 1 survivorCount < 1 survivorCount<1,说明无解,输出 − 1 -1 −1。
-
将初始项链分成若干组,每组的大小为 d e l e t e C o u n t deleteCount deleteCount。如果 d e l e t e C o u n t > s u r v i v o r C o u n t deleteCount > survivorCount deleteCount>survivorCount,则将组数加倍,组的大小减半,直到组的大小不大于 s u r v i v o r C o u n t survivorCount survivorCount。
-
对于每一组,使用不同的字母填充,保证组内字母相同,组间字母不同。
-
在项链的末尾,再添加 s u r v i v o r C o u n t survivorCount survivorCount 个与最后一组不同的字母,作为最终剩余的宝石。
以上步骤可以构造出一种满足条件的初始项链状态。时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( n ) O(n) O(n)。
参考代码
- Python
n, k = map(int, input().split())
delete_count = 1 << (k - 1)
survivor_count = n - delete_count
if survivor_count < 1:
print(-1)
else:
group_count = 1
group_size = delete_count
while group_size > survivor_count:
group_count *= 2
group_size = delete_count // group_count
result = []
for i in range(group_count):
for j in range(group_size):
result.append(chr(ord('a') + i))
survivor = chr(ord(result[-1]) + 1)
result.extend([survivor] * survivor_count)
print(''.join(result))
- Java
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
int k = scanner.nextInt();
int deleteCount = 1 << (k - 1);
int survivorCount = n - deleteCount;
if (survivorCount < 1) {
System.out.println(-1);
} else {
int groupCount = 1;
int groupSize = deleteCount;
while (groupSize > survivorCount) {
groupCount *= 2;
groupSize = deleteCount / groupCount;
}
StringBuilder result = new StringBuilder();
for (int i = 0; i < groupCount; i++) {
for (int j = 0; j < groupSize; j++) {
result.append((char) ('a' + i));
}
}
char survivor = (char) (result.charAt(result.length() - 1) + 1);
for (int i = 0; i < survivorCount; i++) {
result.append(survivor);
}
System.out.println(result.toString());
}
}
}
- Cpp
#include <iostream>
#include <string>
using namespace std;
int main() {
int n, k;
cin >> n >> k;
int deleteCount = 1 << (k - 1);
int survivorCount = n - deleteCount;
if (survivorCount < 1) {
cout << -1 << endl;
} else {
int groupCount = 1;
int groupSize = deleteCount;
while (groupSize > survivorCount) {
groupCount *= 2;
groupSize = deleteCount / groupCount;
}
string result;
for (int i = 0; i < groupCount; i++) {
for (int j = 0; j < groupSize; j++) {
result.push_back('a' + i);
}
}
char survivor = result.back() + 1;
for (int i = 0; i < survivorCount; i++) {
result.push_back(survivor);
}
cout << result << endl;
}
return 0;
}
🎀 写在最后
🛖 这里介绍一下咱们的笔试打卡小屋
✨ 打卡小屋旨在陪伴大家,养成每日学习的好习惯。在这里,你可以:
- 🤝 与备战笔试的小伙伴相识,找到志同道合的学习小组
- 📝 通过写题解,巩固做题思路,养成良好的记录习惯
- 💡 系统掌握常考算法和数据结构,了解互联网笔试难度
- 🎁 坚持打卡,获得丰厚奖励,激励自己持之以恒
🥰 打卡奖励
打卡时长 | 奖励内容 |
---|---|
7天 | 任选一家最新互联网笔试真题 x 1 (价值29.9r) |
14天 | 任选一家最新互联网笔试真题 x 3 + 笔试面试经验贴 |
21天 | 任选一家最新互联网笔试真题 x 5 + 清隆三语言算法模版 |
28天 | 最新互联网大厂笔试真题汇总(价值199r) + 华为OD机试训练营 (价值89r) |
7天打卡即可值回票价,心动不如行动!=>笔试刷题陪伴小屋-打卡赢价值丰厚奖励 <=
🕰 每日学习安排
小屋将在每日上午发放打卡题目,包括:
- 一道算法模版题,帮助大家掌握常用算法套路
- 根据算法模版,精选一道对应的大厂笔试真题,巩固算法应用
让我们一起直击笔试重点,攻克常考题型!
📖 打卡小屋涉及题型
小屋从零基础出发,涵盖笔试常考知识点:
基础算法
- 自定义排序
- 二分
- 前缀和
- 差分
- 双指针
基础数据结构
- 栈 & 单调栈
- 队列 & 单调队列
- 并查集
- 优先队列(堆)
搜索
- DFS & BFS 基础应用
- 树的遍历
- 基础图论
动态规划 & 贪心 & 数论
- 快速幂
- 组合数
- 质数 & 因数
- 位运算
- 基础动态规划
- 常见贪心