恭喜发现宝藏!搜索公众号【TechGuide】回复公司名,解锁更多新鲜好文和互联网大厂的笔经面经,目前已更新至美团、微软…
作者@TechGuide【全网同名】
点赞再看,养成习惯,您动动手指对原创作者意义非凡🤝
第一题:baidu型子串(A/B卷)
题目描述
小红拿到了一个字符串,她想知道有多少个"baidu"型子串?
所谓"baidu“型字符串,指第1个、第4个字母是辅音,第2、3、5个字符是元音,且每个字母都不相同的字符串。
例如,“taigu”、“huida”、“paobu”、"baoli"等都是"baidu"型字符串。
我们定义元音字母仅有’a、‘e’、‘i’、‘o’、'u’这五种,其余字母均为辅音字母。
输入描述
输入一个字符串,长度<=2e5
baiduxiaojiabankanjiaran
输出描述
输出"baidu"型子串的数量
2
解释:"baidu"和"duoxi"合法。其中"jiaba"和"jiara"不合法,因为a出现了2次。
思路
滑动窗口,维护一下窗口内字母特征以及字母出现次数即可。
代码
Python版本
import string
s = input()
if len(s) <= 4:
print(0)
exit(0)
else:
cor = {v: i for i, v in enumerate(string.ascii_lowercase)}
y = set(list('aeiou'))
nums = [0 if i in y else 1 for i in s]
ans = 0
diff = 0
count = [0] * 26
cnt = 0
for i in range(4):
cnt = cnt * 10 + nums[i]
count[cor[s[i]]] += 1
if count[cor[s[i]]] > 1: diff += 1
for i, v in enumerate(s[4:], start=4):
cnt = cnt * 10 + nums[i]
count[cor[v]] += 1
if count[cor[v]] == 2:
diff += 1
if cnt == 10010 and not diff:
ans += 1
cnt -= nums[i - 4] * 10000
count[cor[s[i - 4]]] -= 1
if count[cor[s[i - 4]]] == 1:
diff -= 1
print(ans)
# vx公众号关注TechGuide 实时题库 闪电速递
CPP版本
#include <bits/stdc++.h>
using namespace std;
bool isVow(char c) {
switch(c) {
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
return true;
}
return false;
}
int main() {
string s; cin >> s;
const int n = s.length();
int ans = 0;
for (int i = 0; i < n-4; i++) {
bool allDifferent = true;
for (int j = i; j <= i+4; j++) {
for (int k = j+1; k <= i+4; k++) {
if (s[j] == s[k]) {
allDifferent = false;
break;
}
}
if (!allDifferent) break;
}
if (allDifferent)
ans += !isVow(s[i]) && isVow(s[i+1]) && isVow(s[i+2]) && !isVow(s[i+3]) && isVow(s[i+4]);
}
cout << ans << endl;
return 0;
}
// vx公众号关注TechGuide 实时题库 闪电速递
第二题:01串(A卷)
题目描述
给定一个t,表示接下来有t行数据
给定一个01字符串s,对于每两个连续的子串,你可以把他们变成相反的子串
如 ”01“ 变成”10“ ,“00”变成”11“
如果能把s转换成所有字符相同的字符串,输出”Yes“;否则输出”No”
数据范围 len(s)<2e6
思路
贪心。任意相邻的偶数个0或1,我们可以直接将其反转。而对于奇数个,我们可以反转到只剩下1个0或1。那么最终就只剩下形如 …1…1…1…( ’.'为任意个0)或者…0…0…0…0… ( ’.'为任意个1) 的串。
因为我们只能反转相邻的两个字符,所以我们要把这些1或者0变换到相邻的位置。假设两个1中间有n个0,即100…001,那么我们可以将最右边的两个字符反转,得到100…010,此时两个1中间有n-1个0,相当于把最右边的1往左移了一位。在经过n次反转移位之后,可以得到1100…00,再反转一次就得到全为0的串。(两个0中间有n个1的情况类似)。
这说明了能够成功变换与字符0和字符1的位置无关,只与它们的数量有关。即如果给定串***有偶数个0,我们最终可以变换成全为1的串;如果有偶数个1,我们最终可以变换成全为0的串。
代码
CPP版本
#include <iostream>
using namespace std;
bool ac(string &s) {
int cnt = 0;
for (char c : s) {
cnt += c == '1';
}
return !(cnt&1) || !((s.length()-cnt)&1);
}
int main() {
int q; cin >> q;
while (q--) {
string s;
cin >> s;
cout << (ac(s) ? "Yes" : "No") << endl;
}
return 0;
}
// vx公众号关注TechGuide 实时题库 闪电速递
Python版本
def f(s, c):
n = len(s)
for i in range(n - 1):
if s[i] != c:
s[i + 1] = c if s[i + 1] != c else s[i]
s[i] = c
return s[-1] == c
t = int(input())
for _ in range(t):
s = list(input().strip())
if f(s, "0") or f(s, "1"):
print("Yes")
else:
print("No")
# vx公众号关注TechGuide 实时题库 闪电速递
第三题:走矩阵(A卷)
题目描述
给定一个字符矩阵,矩阵仅由’r’,‘e’,'d’组成。
求从左上角到右下角的最少步数。可以从上下左右四个方向走,但是不能从’r’->‘d’, ‘e’->‘r’,‘d’->‘e’。
第一行输入n m (1<n,m<500)
n表示矩阵的行 m表示矩阵的列
接下来n行 输入一个长为m的”red”字符串
“red”字符串是指所有字符均为”r"或”e"或”d”
你可以在矩阵中上下左右移动
但是r不能移动到d e不能移动到r d不能移动到e
输出从左上角走到右下角最少需要多长时间
如无法到达输出-1
思路
类似最短路径问题 注意需要从终点走向起点
代码
Python版本
from collections import deque
ban = "rderde"
mp = {}
for i in range(0, 5, 2):
mp[ban[i + 1]] = ban[i]
n, m = map(int, input().split())
board = []
for _ in range(n):
s = list(input().strip())
board.append(s)
inf = 10 ** 9
q = deque([(n - 1, m - 1)])
g = [[inf] * m for _ in range(n)]
g[n - 1][m - 1] = 0
while q:
x, y = q.popleft()
for dx, dy in [(0, -1), (0, 1), (1, 0), (-1, 0)]:
nx, ny = dx + x, dy + y
if (
0 <= nx < n
and 0 <= ny < m
and mp[board[x][y]] != board[nx][ny]
and g[nx][ny] == inf
):
g[nx][ny] = g[x][y] + 1
q.append((nx, ny))
if g[0][0] == inf:
print(-1)
else:
print(g[0][0])
# vx公众号关注TechGuide 实时题库 闪电速递
CPP版本
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, m; cin >> n >> m;
vector<string> v(n);
for (int i = 0; i < n; i++) cin >> v[i];
if (n == 1 && m == 1) {
cout << 0 << endl;
return 0;
}
vector<vector<bool>> vis(n, vector<bool>(m));
vis[0][0] = true;
queue<pair<int, int>> q;
q.emplace(0, 0);
int step = 0;
const int dx[]{-1, 0, 1, 0}, dy[]{0, -1, 0, 1};
auto canGo = [] (char from, char to) -> bool {
if (from == 'r' && to == 'd') return false;
if (from == 'e' && to == 'r') return false;
if (from == 'd' && to == 'e') return false;
return true;
};
while (!q.empty()) {
step ++;
int sz = q.size();
while (sz--) {
auto p = q.front(); q.pop();
int x = p.first, y = p.second;
for (int i = 0; i < 4; i++) {
int nx = x+dx[i], ny = y+dy[i];
if (nx == n-1 && ny == m-1 && canGo(v[x][y], v[ny][ny])) {
cout << step << endl;
return 0;
}
if (nx >= 0 && nx < n && ny >= 0 && ny < m && !vis[nx][ny] && canGo(v[x][y], v[nx][ny])) {
vis[nx][ny] = true;
q.emplace(nx, ny);
}
}
}
}
cout << -1 << endl;
return 0;
}
// vx公众号关注TechGuide 实时题库 闪电速递
第四题:打怪物(B卷)
题目描述
有n个怪物排成一排,第i个怪物的血量为ai。小红有两个技能可以打怪:
-
强力攻击,消耗1mp,对一只怪物造成1点伤害。
-
踏前斩,消耗5mp,对当前怪物造成1的伤害,同时剑气将波及后两个怪物,对下一个怪物造成2点伤害,对下下个怪物造成3点伤害。
如果一个怪物受伤后血量小于等于0,则怪物死亡。死亡后怪物的尸体依然占据一个位置,会被踏前斩的剑气打到。
小红想知道,击杀全部怪物至少需要花费多少mp?
输入描述
输入一个n和n个数字作为所有怪物血量
5
1 2 4 2 3
输出描述
输出最小使用的mp
10
思路
贪心即可,因为5hp是可以消耗1+2+3=6滴血的。所以优先使用技能,剩下的普通攻击A掉。
贪心的时候注意从后往前遍历,这样可以通过100%,从前往后遍历只能通过0%。提供case:[1, 9, 8, 9, 8]:
-
从前往后贪:[1,4,8,7,6]–>[0,2,5,7,6]–>[0,0,1,1,6]
从后往前贪:[1,4,8,7,6]–>[1,4,6,3,0]–>[1,3,4,0,0]–>[0,1,1,0,0]
代码
Python版本
n = int(input())
a = list(map(int, input().split()))
ans = 0
i = 0
for i in range(n - 3, -1, -1):
if a[i] >= 1 and a[i + 1] >= 2 and a[i + 2] >= 3:
c = min(a[i], a[i + 1] // 2, a[i + 2] // 3)
a[i] -= c
a[i + 1] -= c * 2
a[i + 2] -= c * 3
ans += c * 5
print(ans + sum(a))
# vx公众号关注TechGuide 实时题库 闪电速递
第五题:for循环(B卷)
题目描述
小红拿到了一段java代码,请你判断其中最多有多少层for循环嵌套。
保证代码合法,且不含注释。循环语句只有for,条件语句只有if,循环语句和条件语句保证包含大括号用来控制范围。
代码中只有一个类和一个主函数。
输入描述
多行输入
import java.util.*;
public class Main{
public static void main(String[] args){
Scanner in = new Scanner(System.in);
int a = 0 , b = 0;
int n = in.nextInt();
for (int i = 0; i < n; i++) {
if ( a < b ) {
a += b / 2;
}
for (int j = 0; j < n; j++) {
b++;
a += b;
}
for (int j = 1; j < n; j *= 2) {
b--;
}
}
System.out.println(a);
}
}
输出描述
输出最大嵌套数
2
思路
模拟题,注意多行输入。维护一个栈维护遇到的大括号和过程值cnt=0,因为题目说了for循环必然使用大括号包裹,那么只需要判断栈入的大括号前面是不是for的大括号即可,如果是就cnt+1,否则就不管。每次遇到右括号就出栈,出栈的时候判断是不是for循环后的括号,如果是就cnt-1,否则就不管。遍历过程中最大的cnt就是结果。
代码
Python版本
import sys
lines = list(sys.stdin.readlines())
a = ''.join(lines)
stack = []
n = len(a)
ans = 0
cnt = 0
pf = 0 # 前一个是不是for
i = 0
while i < n - 4:
if a[i] == '{':
stack.append(pf)
cnt += pf
pf = 0
i += 1
elif a[i] == 'f' and a[i + 1] == 'o' and a[i + 2] == 'r':
pf = 1
i += 3
elif a[i] == '}':
cnt -= stack.pop()
i += 1
else:
i += 1
ans = max(ans, cnt)
print(ans)
# vx公众号关注TechGuide 实时题库 闪电速递