【2023华为od-C卷-第三题-最长的指定瑕疵度的元音子串】100%通过率(JS&Java&Python&C++)

博客介绍了如何使用滑动窗口和双指针解决华为OD题目,寻找具有指定瑕疵度的最长元音子串。文章提供了JavaScript、Java、C++和Python四种语言的实现代码,并给出了样例输入、输出及解题思路。
摘要由CSDN通过智能技术生成

本题已有网友报告代码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 az A − Z A-Z AZ 组成的字符串,字符串长度( $ 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)

这道题是上面这道题的升级版,因为窗口大小不固定,是一个不定长的滑动窗口,也是考的最多的一类双指针问题

使用双指针lr来维护区间左端点和区间右端点都是元音字母,且区间中的辅音字母数量等于题目给定的数量 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)  # 输出最大长度
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
华为OD平台上,要求使用Java编程语言编写程序,寻找符合要求的最长子串。 首先,我们需要明确“最长子串”的概念。最长子串是指在一个给定字符串中的一段连续子字符串中,包含字符个数最多的子串。例如,在字符串“abcabcbb”中,最长子串为“abc”,长为3。 要编写一个寻找最长子串的程序,可以使用双指针法。首先,我们用两个指针i和j来遍历字符串,i用于记录子串的起始位置,j用于记录子串的结束位置。我们还使用一个HashMap来存储字符及其在子串中的索引。 具体的算法如下: 1. 初始化i和j为0,表示子串的起始和结束位置。 2. 初始化maxLen为0,表示最长子串的长。 3. 创建一个HashMap来保存字符及其在子串中的索引。 4. 从i开始遍历字符串,将字符及其索引添加到HashMap中。 5. 如果当前字符已经在HashMap中存在且其在子串中的索引大于等于i,则将i移动到该字符的下一个位置。 6. 计算当前子串的长,如果大于maxLen,则更新maxLen,并更新子串的起始和结束位置。 7. 将当前字符及其索引添加到HashMap中。 8. 将j向右移动一位。 9. 重复步骤4到8,直到遍历完整个字符串。 10. 返回最长子串的长子串本身。 以上就是用Java编程语言华为OD平台上寻找符合要求的最长子串的方法。根据不同的需求,我们可以根据这个基础算法进行适当的修改和优化。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

塔子哥学算法

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值