🍭 大家好这里是清隆学长 ,一枚热爱算法的程序员
💻 ACM银牌🥈| 多次AK大厂笔试 | 编程一对一辅导
✨ 本系列打算持续跟新 秋招笔试题
👏 感谢大家的订阅➕ 和 喜欢💗
📧 清隆这边最近正在收集近一年半互联网笔试题汇总,有需要的小伙伴可以关注 文末 公主号领取~
文章目录
- 🎀 01.A先生的环形花圃
- 题目描述
- 输入格式
- 输出格式
- 样例输入
- 样例输出
- 数据范围
- 题解
- 参考代码
- 🪐 02.卢小姐的音游金币
- 问题描述
- 输入格式
- 输出格式
- 样例输入
- 样例输出
- 样例说明
- 样例输入 2
- 样例输出 2
- 样例说明 2
- 数据范围
- 题解
- 参考代码
- ✨ 03.卢小姐的独特花园
- 问题描述
- 输入格式
- 输出格式
- 样例输入
- 样例输出
- 数据范围
- 题解
- 参考代码
- 🥝 04.LYA的字符画
- 题目描述
- 输入格式
- 输出格式
- 样例输入
- 样例输出
- 数据范围
- 题解
- 参考代码
- 🌸 05.卢小姐的数组删除计划
- 题目名称
- 问题描述
- 输入格式
- 输出格式
- 样例输入
- 样例输出
- 数据范围
- 题解
- 参考代码
- 写在最后
- 🎧 秋招陪伴刷题打卡
- ✈️ 超全的笔试题汇总
🎀 01.A先生的环形花圃
题目描述
A先生有一个环形的花圃,花圃被分成了 n n n 块区域。最初,A先生在花圃上选择了三块区域种植了玫瑰。
现在,A先生想要通过移动操作,使得花圃达到平衡状态。
平衡状态:任意两块种植玫瑰的区域之间的距离不小于 k k k(相邻区域的距离为 1 1 1)。
移动操作:交换相邻区域的状态(玫瑰区域变为空区域,空区域变为玫瑰区域)。
同时,A先生是一个很注重效率的人,所以他希望你能使用最少的移动次数使得花圃达到平衡状态。
输入格式
第一行输入一个正整数 t t t,表示询问次数。
接下来 t t t 行,每行包含五个正整数 n n n、 k k k、 a 1 a_1 a1、 a 2 a_2 a2、 a 3 a_3 a3,分别表示花圃区域的数量、要求的最小距离以及三块玫瑰区域的初始位置。
输出格式
输出 t t t 行,每行输出一个整数,表示使花圃达到平衡状态所需的最小交换次数。如果无法达到平衡状态,则输出 − 1 -1 −1。
样例输入
3
5 1 1 2 3
5 2 1 2 3
6 2 2 3 6
样例输出
0
-1
1
数据范围
1 ≤ t ≤ 1 0 4 1 \leq t \leq 10^4 1≤t≤104
1 ≤ n ≤ 1 0 9 1 \leq n \leq 10^9 1≤n≤109
1 ≤ k , a 1 , a 2 , a 3 ≤ n 1 \leq k, a_1, a_2, a_3 \leq n 1≤k,a1,a2,a3≤n
题解
本题可以通过分析平衡状态的条件来解决。
首先,如果要求的最小距离 k k k 超过了花圃区域数量 n n n 的三分之一,则无论如何都无法满足条件,此时输出 − 1 -1 −1。
否则,我们可以先将三个玫瑰区域的位置排序,然后计算出相邻玫瑰区域之间的距离。接下来,对于每个距离,如果它小于 k k k,则需要进行移动操作,移动次数为 k k k 与该距离之差。
最终,所有距离都满足要求时,花圃即达到平衡状态,输出总的移动次数即可。
时间复杂度为 O ( t log t ) O(t \log t) O(tlogt),空间复杂度为 O ( 1 ) O(1) O(1)。
参考代码
- Python
t = int(input())for _ in range(t):n, k, *a = map(int, input().split())a.sort()if k * 3 > n:print(-1)continueb = [a[1] - a[0], a[2] - a[1], n - a[2] + a[0]]ans = sum(max(0, k - d) for d in b)print(ans)
- Java
import java.util.Arrays;
import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int t = sc.nextInt();while (t-- > 0) {int n = sc.nextInt();int k = sc.nextInt();int[] a = new int[3];for (int i = 0; i < 3; i++) {a[i] = sc.nextInt();}Arrays.sort(a);if (k * 3 > n) {System.out.println(-1);continue;}int[] b = {a[1] - a[0], a[2] - a[1], n - a[2] + a[0]};int ans = 0;for (int d : b) {ans += Math.max(0, k - d);}System.out.println(ans);}}
}
- Cpp
#include <iostream>
#include <algorithm>using namespace std;int main() {int t;cin >> t;while (t--) {int n, k, a[3];cin >> n >> k >> a[0] >> a[1] >> a[2];sort(a, a + 3);if (k * 3 > n) {cout << -1 << endl;continue;}int b[] = {a[1] - a[0], a[2] - a[1], n - a[2] + a[0]};int ans = 0;for (int d : b) {ans += max(0, k - d);}cout << ans << endl;}return 0;
}
🪐 02.卢小姐的音游金币
问题描述
卢小姐最近沉迷于一款以钢琴音为主的音游。在游戏中,每个钢琴块都有一个编号,编号最小为 1 1 1。如果连续击中五个编号连续递增的钢琴块,就会获得一个金币。
举个例子,如果卢小姐在一个关卡中依次击中了编号为 1, 2, 3, 4, 5, 6
的钢琴块,那么对于 1, 2, 3, 4, 5
这五个编号连续递增的块,她就会获得一个金币。
当一个关卡进行了很久后,编号会重置,重置后的编号从 1 1 1 开始。所以对于一个关卡来说,可能会击中多个编号相同但不同的钢琴块。
注意,这里只要求在同一关卡中,五个编号连续递增的钢琴块,即可获得金币。
由于卢小姐实力超群,她已经通过了四个关卡。现在给出了卢小姐在四个难度关卡 A A A、 B B B、 C C C 和 D D D 中击中的钢琴块编号,请问在这四个关卡中,卢小姐总共能够获得多少金币。
输入格式
第一行包含一个正整数 n n n( 1 ≤ n ≤ 1 0 5 1 \leq n \leq 10^5 1≤n≤105),代表卢小姐在四个关卡中击中的钢琴块总数。
接下来的 n n n 行,每行输入三个参数: a i a_i ai、 b i b_i bi( 1 ≤ a i , b i ≤ 1 0 9 1 \leq a_i, b_i \leq 10^9 1≤ai,bi≤109)和 c i c_i ci( c i ∈ { ′ A ′ , ′ B ′ , ′ C ′ , ′ D ′ } c_i \in \{'A', 'B', 'C', 'D'\} ci∈{′A′,′B′,′C′,′D′}),分别代表每个钢琴块的编号、数量以及所在的关卡。
输出格式
输出一个整数,表示卢小姐能够获得的金币总数。
样例输入
11
1 1 A
2 2 A
3 2 A
4 2 A
5 2 A
6 1 A
7 1 B
8 2 B
9 2 B
10 2 B
11 1 B
样例输出
3
样例说明
对于关卡 A A A,首先 1, 2, 3, 4, 5
可以获得一个金币,然后 2, 3, 4, 5, 6
可以再获得一个金币。
对于关卡 B B B,7, 8, 9, 10, 11
可以获得一个金币。
因此,总共可以获得 3 3 3 个金币。
样例输入 2
5
1 1 C
2 2 C
3 2 C
4 2 C
6 1 C
样例输出 2
0
样例说明 2
在关卡 C C C 中,无法得到五个连续递增的编号,因此金币数为 0 0 0。
数据范围
- 1 ≤ n ≤ 1 0 5 1 \leq n \leq 10^5 1≤n≤105
- 1 ≤ a i , b i ≤ 1 0 9 1 \leq a_i, b_i \leq 10^9 1≤ai,bi≤109
- c i ∈ { ′ A ′ , ′ B ′ , ′ C ′ , ′ D ′ } c_i \in \{'A', 'B', 'C', 'D'\} ci∈{′A′,′B′,′C′,′D′}
题解
本题可以使用哈希表和排序来解决。具体思路如下:
-
使用哈希表
cnt
记录每个关卡中每个编号出现的次数。键为关卡字符与编号的组合,值为该编号在该关卡中出现的次数。 -
将输入的数据按照关卡字符和编号排序,确保相同关卡的编号是连续的。
-
遍历排序后的数据,对于每个编号,判断其连续的五个编号是否都存在于当前关卡中。如果存在,则取这五个编号中出现次数的最小值,计入答案,并将这五个编号的出现次数都减去该最小值。
-
最终答案即为所有满足条件的金币数之和。
时间复杂度为 O ( n log n ) O(n \log n) O(nlogn),空间复杂度为 O ( n ) O(n) O(n)。
参考代码
- Python
from collections import defaultdict
import sysdef solve():n = int(input())cnt = defaultdict(int)vec = []for _ in range(n):a, b, c = input().split()a, b = int(a), int(b)cnt[c + str(a)] += bvec.append((c, a))vec.sort()ans = 0for v in vec:arr = [v[0] + str(v[1] + i) for i in range(5)]t = min(cnt[a] for a in arr)ans += tfor a in arr:cnt[a] -= tprint(ans)if __name__ == '__main__':solve()
- Java
import java.io.*;
import java.util.*;public class Main {public static void main(String[] args) throws IOException {BufferedReader br = new BufferedReader(new InputStreamReader(System.in));int n = Integer.parseInt(br.readLine());Map<String, Integer> cnt = new HashMap<>();List<int[]> vec = new ArrayList<>();for (int i = 0; i < n; i++) {String[] input = br.readLine().split(" ");int a = Integer.parseInt(input[0]);int b = Integer.parseInt(input[1]);String c = input[2];String key = c + a;cnt.put(key, cnt.getOrDefault(key, 0) + b);vec.add(new int[]{c.charAt(0), a});}vec.sort((x, y) -> {if (x[0] != y[0]) {return x[0] - y[0];}return x[1] - y[1];});long ans = 0;for (int[] v : vec) {String[] arr = new String[5];for (int i = 0; i < 5; i++) {arr[i] = (char) v[0] + String.valueOf(v[1] + i);}int t = Integer.MAX_VALUE;for (String a : arr) {t = Math.min(t, cnt.getOrDefault(a, 0));}ans += t;for (String a : arr) {cnt.put(a, cnt.get(a) - t);}}System.out.println(ans);}
}
- Cpp
#include <iostream>
#include <vector>
#include <map>
#include <algorithm>
#include <climits>
using namespace std;using ll = long long;int main() {int n;cin >> n;map<string, ll> cnt;vector<pair<string, int>> vec;for (int i = 1; i <= n; i++) {int a, b;string c;cin >> a >> b >> c;cnt[c + to_string(a)] += b;vec.push_back({c, a});}sort(vec.begin(), vec.end());ll ans = 0;for (auto& v : vec) {vector<string> arr;for (int i = 0; i < 5; i++) {arr.push_back(v.first + to_string(v.second + i));}ll t = LLONG_MAX;for (auto& a : arr) {t = min(t, cnt[a]);}ans += t;for (auto& a : arr) {cnt[a] -= t;}}cout << ans << endl;return 0;
}
✨ 03.卢小姐的独特花园
问题描述
卢小姐有一个长度为 n n n 的花园,花园中种植着 n n n 种不同的花。每种花都有一个美丽值 a i a_i ai。
卢小姐觉得一个美丽的花园应该是独特的,即有 n − 1 n-1 n−1 种花的美丽值相同,只有 1 1 1 种花的美丽值与其他花不同。
每次操作,卢小姐可以选择一种花,将其美丽值加 1 1 1 或减 1 1 1。
现在,卢小姐想知道,至少需要多少次操作,才能将花园变得独特。
输入格式
第一行包含一个正整数 n n n,表示花园的长度。
第二行包含 n n n 个正整数 a 1 , a 2 , … , a n a_1, a_2, \ldots, a_n a1,a2,…,an,表示每种花的美丽值。
输出格式
输出一个整数,表示将花园变得独特所需的最少操作次数。
样例输入
4
1 2 3 4
样例输出
2
数据范围
- 1 ≤ n ≤ 1 0 5 1 \leq n \leq 10^5 1≤n≤105
- 1 ≤ a i ≤ 1 0 9 1 \leq a_i \leq 10^9 1≤ai≤109
题解
最优解是变成中位数,枚举所有变成中位数的代价
时间复杂度为 O ( n log n ) O(n \log n) O(nlogn),空间复杂度为 O ( n ) O(n) O(n)。
参考代码
- Python
def main():n = int(input())w = list(map(int, input().split()))w.sort()if w[0] == w[n - 1]:print("1")returns1, s2 = 0, 0m1, m2 = w[(n - 1) // 2], w[(n + 1) // 2]for i in range(n - 1):s1 += abs(m1 - w[i])for i in range(1, n):s2 += abs(m2 - w[i])print(min(s1, s2))if __name__ == "__main__":main()
- Java
import java.util.*;public class Main {public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int n = scanner.nextInt();int[] w = new int[n];for (int i = 0; i < n; i++)w[i] = scanner.nextInt();Arrays.sort(w);if (w[0] == w[n - 1]) {System.out.println("1");return;}long s1 = 0, s2 = 0;int m1 = w[(n - 1) / 2], m2 = w[(n + 1) / 2];for (int i = 0; i < n - 1; i++)s1 += Math.abs(m1 - w[i]);for (int i = 1; i < n; i++)s2 += Math.abs(m2 - w[i]);System.out.println(Math.min(s1, s2));}
}
- Cpp
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
const int N = 100010;int main() {int n, w[N];cin >> n;for (int i = 0; i < n; i++)cin >> w[i];sort(w, w + n);if (w[0] == w[n - 1]) {cout << "1" << endl;return 0;}ll s1 = 0, s2 = 0;int m1 = w[(n - 1) / 2], m2 = w[(n + 1) / 2];for (int i = 0; i < n - 1; i++)s1 += abs(m1 - w[i]);for (int i = 1; i < n; i++)s2 += abs(m2 - w[i]);cout << min(s1, s2) << endl;return 0;
}
🥝 04.LYA的字符画
题目描述
LYA最近迷上了字符画,她认为一个字符画的美观度等于字符画中连续相同符号的数量。例如,字符画"aabbccddef"的美观度为 6 6 6。
LYA的朋友给了她一个由 0 0 0 和 1 1 1 组成的字符串,已经迷恋上字符画的LYA想知道,这个字符串的所有子串的美观度之和是多少?
注:共有 C n + 1 2 C^{2}_{n+1} Cn+12 个子串。
输入格式
第一行输入一个正整数 n n n,表示字符串的长度。
第二行为长度为 n n n 的 01 01 01 字符串。
输出格式
输出一个整数,表示所有子串的美观度之和。
样例输入
4
0011
样例输出
14
数据范围
1 ≤ n ≤ 2 × 1 0 5 1 \leq n \leq 2 \times 10^5 1≤n≤2×105
题解
本题可以通过前缀和的思想来解决。
首先,我们可以计算出字符串的总子串数,即 n ( n + 1 ) 2 \frac{n(n+1)}{2} 2n(n+1)。
然后,我们遍历字符串,用变量 l l l 记录当前连续相同符号的起始位置,变量 r r r 记录当前位置。当 s [ r ] ≠ s [ r − 1 ] s[r] \neq s[r-1] s[r]=s[r−1] 时,说明出现了新的符号,我们可以计算出 [ l , r ) [l, r) [l,r) 区间内的子串数,即 ( r − l ) ( r − l + 1 ) 2 \frac{(r-l)(r-l+1)}{2} 2(r−l)(r−l+1),将其从总子串数中减去。
最后,剩下的就是所有美观子串的数量,输出即可。
时间复杂度 O ( n ) O(n) O(n),空间复杂度 O ( 1 ) O(1) O(1)。
参考代码
- Python
def cal(length):return length * (length + 1) // 2n = int(input())
s = input() + '#'ans = 0
total = cal(n)
l = 0
for r in range(1, n + 1):if s[r] != s[r - 1]:ans += total - cal(l) - cal(n - r)l = rprint(ans)
- 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 s = sc.next() + "#";long ans = 0;long total = cal(n);int l = 0;for (int r = 1; r <= n; r++) {if (s.charAt(r) != s.charAt(r - 1)) {ans += total - cal(l) - cal(n - r);l = r;}}System.out.println(ans);}private static long cal(int len) {return (long) len * (len + 1) / 2;}
}
- Cpp
#include <iostream>
#include <string>using namespace std;using ll = long long;ll cal(int len) {return (ll) len * (len + 1) / 2;
}int main() {int n;cin >> n;string s;cin >> s;s += "#";ll ans = 0;ll total = cal(n);int l = 0;for (int r = 1; r <= n; r++) {if (s[r] != s[r - 1]) {ans += total - cal(l) - cal(n - r);l = r;}}cout << ans << endl;return 0;
}
🌸 05.卢小姐的数组删除计划
题目名称
问题描述
卢小姐有一个非常宏伟的计划,她想要删除世界上所有的数组!但是她的能力有限,每次只能选择数组中的两个相同元素,并删除它们之间的所有元素(包括这两个元素本身)。
现在,卢小姐面前有一个长度为 n n n 的数组 a a a,她想知道自己最多能够删除这个数组中的多少个元素。
输入格式
第一行包含一个正整数 n n n,表示数组 a a a 的长度。
第二行包含 n n n 个空格分隔的正整数 a 1 , a 2 , … , a n a_1, a_2, \ldots, a_n a1,a2,…,an,表示数组 a a a 的元素。
输出格式
输出一个整数,表示卢小姐最多能够删除的元素个数。
样例输入
4
1 2 1 2
样例输出
1
数据范围
- 1 ≤ n ≤ 2 × 1 0 5 1 \leq n \leq 2 \times 10^5 1≤n≤2×105
- 1 ≤ a i ≤ 1 0 9 1 \leq a_i \leq 10^9 1≤ai≤109
题解
本题可以使用排序和双指针的思想来解决。
首先,我们可以将数组 a a a 中的元素按照值进行排序,并记录每个元素原本在数组中的位置。这样做的目的是为了方便我们找到相同元素的位置范围。
接下来,我们可以遍历排序后的数组,对于每个元素,找到与其值相同的所有元素的位置范围 [ L , R ] [L, R] [L,R]。这个范围内的元素都是可以被删除的,因为它们在原数组中位于两个相同元素之间。我们可以计算出范围 [ L , R ] [L, R] [L,R] 内的元素个数,即 R − L − 1 R - L - 1 R−L−1,将其与当前的最大删除元素个数进行比较,更新最大值。
最后,输出最大的删除元素个数即可。
时间复杂度为 O ( n log n ) O(n \log n) O(nlogn),主要是排序的时间复杂度。空间复杂度为 O ( n ) O(n) O(n),用于存储元素的原始位置。
参考代码
- Python
n = int(input())
a = list(map(int, input().split()))idx = sorted(range(n), key=lambda x: a[x])ans = 0
i = 0
while i < n:j = iL, R = n, -1while j < n and a[idx[j]] == a[idx[i]]:L = min(L, idx[j])R = max(R, idx[j])j += 1ans = max(ans, R - L - 1)i = jprint(ans)
- Java
import java.util.*;public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();int[] a = new int[n];Integer[] idx = new Integer[n];for (int i = 0; i < n; i++) {a[i] = sc.nextInt();idx[i] = i;}Arrays.sort(idx, Comparator.comparingInt(i -> a[i]));int ans = 0;for (int i = 0; i < n;) {int j = i;int L = n, R = -1;while (j < n && a[idx[j]] == a[idx[i]]) {L = Math.min(L, idx[j]);R = Math.max(R, idx[j]);j++;}ans = Math.max(ans, R - L - 1);i = j;}System.out.println(ans);}
}
- Cpp
#include <iostream>
#include <vector>
#include <algorithm>using namespace std;int main() {int n;cin >> n;vector<int> a(n);vector<int> idx(n);for (int i = 0; i < n; i++) {cin >> a[i];idx[i] = i;}sort(idx.begin(), idx.end(), [&](int i, int j) {return a[i] < a[j];});int ans = 0;for (int i = 0; i < n;) {int j = i;int L = n, R = -1;while (j < n && a[idx[j]] == a[idx[i]]) {L = min(L, idx[j]);R = max(R, idx[j]);j++;}ans = max(ans, R - L - 1);i = j;}cout << ans << endl;return 0;
}
写在最后
这边给大家推荐一下 学长的秋招陪伴打卡小屋啦,31天 带你一步一步解决常见互联网笔试题型,每天都是干货满满哦。
🎧 秋招陪伴刷题打卡
- 试读:
【秋招刷题打卡】Day01-自定义排序-CSDN博客
【秋招刷题打卡】Day02-最强二分系列之-二分查找-CSDN博客
【秋招刷题打卡】Day03-最强二分系列之-二分答案-CSDN博客
提供往期大厂真题在线评测,感兴趣的小伙伴可以私信清隆详细了解哦
还有! 还有!还有!
✈️ 超全的笔试题汇总