本题已有网友报告代码100%通过率
OJ &答疑服务
购买任意专栏,即可私信博主,获取答疑/辅导服务
OJ权限获取可以在购买专栏后访问网站:首页 - CodeFun2000
题目描述
开头和结尾都是元音字母( a e i o u A E I O U
)的字符串为元音字符串,其中混杂的非元音字母数量为其瑕疵度,比如:
“ a a a”、" a a aa aa " 是元音字母,其瑕疵度为 0 0 0
" a i u r aiur aiur "不是元音字符串(结尾不是元音字符)
" a b i r a abira abira "是元音字符串,其瑕疵度为 2 2 2
给定一个字符串,请找出指定瑕疵度的最长元音字符子串,并输出其长度,如果找不到满足条件的元音字符字串,输出为" 0 0 0 "。
字串:字符串中任意连续的字符组成的子序列称为该字符串的子串。
输入描述
首行输入是一个整数,表示预期的瑕疵度 f l a w flaw flaw ,取值范围[ 0 , 65535 0 , 65535 0,65535 ]。
接下俩一行是一个仅由字符 a − z a-z a−z 和 A − Z A-Z A−Z 组成的字符串,字符串长度( $ 0,65535$ ]。
输出描述
输出为一个整数,代表满足条件的元音字符字串的长度。
样例1
输入
0
asdbuiodevauufgh
输出
3
说明:满足条件的最长元音字符子串有两个,分别为 u i o uio uio 和 a u u auu auu ,长度为3
样例2
输入
2
aeueo
输出
0
说明:没有满足条件的元音字符字串,输出为 0 0 0
样例3
输入
1
aabeebuu
输出
5
说明:满足条件的最长元音字符字串有两个,分别为 a a b e e aabee aabee 和 e e b u u eebuu eebuu ,长度为 5 5 5
思路:滑动窗口/双指针
简单版题目可以参考LeetCode原题:1456. 定长子串中元音的最大数目 - 力扣(LeetCode)
这道题是上面这道题的升级版,因为窗口大小不固定,是一个不定长的滑动窗口,也是考的最多的一类双指针问题
使用双指针l
和r
来维护区间左端点和区间右端点都是元音字母,且区间中的辅音字母数量等于题目给定的数量
f
l
a
w
flaw
flaw,一边移动指针,一边更新区间长度最大值。
JavaScript代码
const st = new Set("aeiouAEIOU"); // 存有元音字母的集合
let k = 0;
let s = '';
const readline = require('readline');
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
let lineCount = 0;
rl.on('line', (line) => {
if (lineCount === 0) {
k = parseInt(line);
} else if (lineCount === 1) {
s = line;
let l = 0, r = 0, ans = 0, cnt = 0; // 初始化双指针 l 和 r,结果 ans,以及辅音个数计数器 cnt
while (r < s.length) {
if (!st.has(s[r])) { // 如果当前字符是辅音
cnt++; // 辅音个数加一
} else {
while (cnt > k || !st.has(s[l])) { // 当辅音个数大于 k 或者 L 指向的字符是辅音时就将左指针向前移动
if (!st.has(s[l])) { // 如果 L 移动前指向的字符是辅音,就将计数减一
cnt--;
}
l++; // 指针向前移动
}
if (cnt === k) { // 如果辅音个数等于 k,也就是符合题目要求的子串
ans = Math.max(ans, r - l + 1); // 更新最大长度
}
}
r++; // R 指针右移
}
console.log(ans); // 输出最大长度
k = 0;
s = '';
}
lineCount++;
});
Java代码
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int k = sc.nextInt();
String s = sc.next();
boolean[] f = new boolean[s.length()]; // 判断字符串中每个字符是否为元音,并存储结果到列表 f 中
for (int i = 0; i < s.length(); i++) {
f[i] = isy(s.charAt(i));
}
int L = 0, R = 0, ans = 0, cnt = 0; // 初始化双指针 L 和 R,结果 ans,以及辅音个数计数器 cnt
while (R < s.length()) {
if (!f[R]) { // 如果当前字符是辅音
cnt++; // 辅音个数加一
} else {
while (cnt > k || !f[L]) { // 当辅音个数大于 k 或者 L 指向的字符是辅音时就将左指针向前移动
if (!f[L]) { // 如果 L 移动前指向的字符是辅音,就将计数减一
cnt--;
}
L++; // 指针向前移动
}
if (cnt == k) { // 如果辅音个数等于 k,也就是符合题目要求的子串
ans = Math.max(ans, R-L+1); // 更新最大长度
}
}
R++; // R 指针右移
}
System.out.println(ans); // 输出最大长度
}
static boolean isy(char ch) { // 判断ch是否为元音字母
return ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u' || ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U';
}
}
C++代码
#include <iostream>
#include <string>
#include <vector>
using namespace std;
bool isy(char ch) { // 判断ch是否为元音字母
return ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u' || ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U';
}
int main() {
int k;
string s;
cin >> k >> s;
vector<bool> f(s.size()); // 判断字符串中每个字符是否为元音,并存储结果到列表 f 中
for (int i = 0; i < s.size(); i++) {
f[i] = isy(s[i]);
}
int L = 0, R = 0, ans = 0, cnt = 0; // 初始化双指针 L 和 R,结果 ans,以及辅音个数计数器 cnt
while (R < s.size()) {
if (!f[R]) { // 如果当前字符是辅音
cnt++; // 辅音个数加一
} else {
while (cnt > k || !f[L]) { // 当辅音个数大于 k 或者 L 指向的字符是辅音时就将左指针向前移动
if (!f[L]) { // 如果 L 移动前指向的字符是辅音,就将计数减一
cnt--;
}
L++; // 指针向前移动
}
if (cnt == k) { // 如果辅音个数等于 k,也就是符合题目要求的子串
ans = max(ans, R-L+1); // 更新最大长度
}
}
R++; // R 指针右移
}
cout << ans << endl; // 输出最大长度
return 0;
}
Python代码
st=set("aeiouAEIOU") #存有元音字母的集合
k = int(input())
s = input()
l,r,ans, cnt = 0, 0, 0, 0 # 初始化双指针 l和 r,结果 ans,以及辅音个数计数器 cnt
while r < len(s):
if s[r] not in st: # 如果当前字符是辅音
cnt += 1 # 辅音个数加一
else:
while cnt > k or s[l] not in st:
# 当辅音个数大于 k 或者 L 指向的字符是辅音时就将左指针向前移动
if s[l] not in st: # 如果 L 移动前指向的字符是辅音,就将计数减一
cnt -= 1
l += 1 # 指针向前移动
if cnt == k: # 如果辅音个数等于 k,也就是符合题目要求的子串
ans = max(ans, r-l+1) # 更新最大长度
r += 1 # R 指针右移
print(ans) # 输出最大长度