【2023C卷题限时免费】20天拿下华为OD笔试之 【不定滑窗】2023C-最长的指定瑕疵度的元音子串【欧弟算法】全网注释最详细分类最全的华为OD真题题解

文章目录

  • 题目描述与示例
    • 题目描述
    • 输入描述
    • 输出描述
    • 示例一
      • 输入
      • 输出
      • 说明
    • 示例二
      • 输入
      • 输出
      • 说明
    • 示例三
      • 输入
      • 输出
      • 说明
  • 解题思路
    • 滑窗三问
    • 滑窗三答
  • 代码
    • Python
    • Java
    • C++
    • 时空复杂度
  • 华为OD算法/大厂面试高频题算法练习冲刺训练

题目描述与示例

题目描述

头和结尾都是元音字母(aeiouAEIOU)的字符串为元音字符串,其中混杂的非元音字母数量为其瑕疵度。比如:

  • "a""aa"是元音字符串,其瑕疵度都为 0
  • "aiur"不是元音字符串(结尾不是元音字符)
  • "abira"是元音字符串,其瑕疵度为 2

给定一个字符串,请找出指定瑕疵度的最长元音字符子串,并输出其长度,如果找不到满足条件的元音字符子串,输出 0

子串:字符串中任意个连续的字符组成的子序列称为该字符串的子串。

输入描述

首行输入是一个整数,表示预期的瑕疵度flaw,取值范围[0, 65535]

接下来一行是一个仅由字符a-zA-Z组成的字符串,字符串长度(0, 65535]

输出描述

输出为一个整数,代表满足条件的元音字符子串的长度。

示例一

输入

0
asdbuiodevauufgh

输出

3

说明

满足条件的最长元音字符子串有两个,分别为uioauu,长度为 3

示例二

输入

2
aeueo

输出

0

说明

没有满足条件的元音字符子串,输出 0

示例三

输入

1
aabeebuu

输出

1

说明

满足条件的最长元音字符子串有两个,分别为aabeeeebuu,长度为 5

解题思路

本题很显然是要找到一个最长的滑动窗口,窗口需要满足以下两个条件:

  1. 首尾的字符都是元音
  2. 窗口中的辅音个数不超过k个(即瑕疵度)

窗口的辅音个数,可以用一个变量win_consonant_num来维护即可。要特别注意一点,因为元音子串要求子串首尾的字符都是元音,我们必须固定left的位置始终指向一个元音,这使得

  1. left右移的条件会和常规的滑窗问题略有不同。
  2. 在开始滑窗时,必须先找到最左边的第一个元音作为left的起始位置以及滑窗的开始位置。

滑窗三问

Q1:对于每一个右指针right所指的元素ch,做什么操作?

Q2:什么时候要令左指针left右移?left对应的元素做什么操作?while中的循环不变量是什么?

Q3:什么时候进行ans的更新?

滑窗三答

A1:如果ch是一个辅音,则窗口中辅音个数win_consonant_num += 1

A2win_consonant_num > k,即滑窗子串所对应的瑕疵度超过了瑕疵度阈值kleft右移,直到left指向一个元音。

A3:如果ch是一个元音,且此时瑕疵度恰好为k,那么可以更新答案。

代码

Python

# 题目:【不定滑窗】2023C-最长的指定瑕疵度的元音子串
# 分值:200
# 作者:许老师-闭着眼睛学数理化
# 算法:不定滑窗
# 代码看不懂的地方,请直接在群上提问


# 输入瑕疵度
k = int(input())
# 输入原字符串
s = input()

# 构建包含元音的集合,用于快速判断某字符是不是元音
vowel_set = set("aeiouAEIOU")

n = len(s)
# 初始化滑窗的左指针left是n
left = n
# 找到第一个元音
for i in range(n):
    if s[i] in vowel_set:
        left = i
        break

# 如果经过上述循环后,left仍是n
# 说明s中不存在元音,也不存在符合要求的子串
# 直接输出0
if left == n:
    print(0)
else:
    ans = 0
    # 初始化滑窗中的辅音个数为0
    win_consonant_num = 0
    # 进行滑窗,从下标left开始滑窗
    for right, ch in enumerate(s[left:], left):
        # A3:如果ch是一个元音,且瑕疵度恰好为k,那么可以更新答案。
        if ch in vowel_set:
            if win_consonant_num == k:
                ans = max(ans, right-left+1)
        # A1:如果ch是一个辅音,则窗口中辅音个数win_consonant_num += 1
        else:
            win_consonant_num += 1
            # A2:即滑窗子串所对应的瑕疵度超过了瑕疵度阈值k,left右移,
            # 由于元音子串的首尾必须均为元音
            # 因此left需要持续右移直到以下两个条件均满足:
            # 1. win_consonant_num <= k
            # 2. s[left]指向一个元音
            while left < n and (win_consonant_num > k or s[left] not in vowel_set):
                if s[left] not in vowel_set:
                    win_consonant_num -= 1
                left += 1

    # 退出循环,ans即为答案
    print(ans)

Java

import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        // 输入瑕疵度
        int k = scanner.nextInt();
        scanner.nextLine();  // 读取换行符

        // 输入原字符串
        String s = scanner.nextLine();

        // 构建包含元音的集合
        Set<Character> vowelSet = new HashSet<>();
        vowelSet.add('a');
        vowelSet.add('e');
        vowelSet.add('i');
        vowelSet.add('o');
        vowelSet.add('u');
        vowelSet.add('A');
        vowelSet.add('E');
        vowelSet.add('I');
        vowelSet.add('O');
        vowelSet.add('U');

        int n = s.length();
        int left = n;

        // 找到第一个元音
        for (int i = 0; i < n; i++) {
            if (vowelSet.contains(s.charAt(i))) {
                left = i;
                break;
            }
        }

        // 如果不存在元音
        if (left == n) {
            System.out.println(0);
        } else {
            int ans = 0;
            int winConsonantNum = 0;

            for (int right = left; right < n; right++) {
                char ch = s.charAt(right);

                // 如果 ch 是元音
                if (vowelSet.contains(ch)) {
                    if (winConsonantNum == k) {
                        ans = Math.max(ans, right - left + 1);
                    }
                } else {  // 如果 ch 是辅音
                    winConsonantNum++;

                    // 如果滑窗子串对应的瑕疵度超过了阈值 k
                    while (left < n && (winConsonantNum > k || !vowelSet.contains(s.charAt(left)))) {
                        if (!vowelSet.contains(s.charAt(left))) {
                            winConsonantNum--;
                        }
                        left++;
                    }
                }
            }

            // 输出结果
            System.out.println(ans);
        }
    }
}

C++

#include 
#include 
using namespace std;

int main() {
    // 输入瑕疵度
    int k;
    cin >> k;

    // 输入原字符串
    string s;
    cin.ignore();  // 忽略换行符
    getline(cin, s);

    // 构建包含元音的集合
    unordered_set<char> vowelSet = {'a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U'};

    int n = s.length();
    int left = n;


    // 找到第一个元音
    for (int i = 0; i < n; i++) {
        if (vowelSet.count(s[i]) == 1) {
            left = i;
            break;
        }
    }

    // 如果不存在元音
    if (left == n) {
        cout << 0 << endl;
    } else {
        int ans = 0;
        int winConsonantNum = 0;
        int start = left;
        for (int right = start; right < n; right++) {
            char ch = s[right];

            // 如果 ch 是元音
            if (vowelSet.count(ch)) {
                if (winConsonantNum == k) {
                    ans = max(ans, right - left + 1);
                }
            } else {  // 如果 ch 是辅音
                winConsonantNum++;

                // 如果滑窗子串对应的瑕疵度超过了阈值 k
                while (left < n && (winConsonantNum > k || !vowelSet.count(s[left]))) {
                    if (!vowelSet.count(s[left])) {
                        winConsonantNum--;
                    }
                    left++;
                }
            }
        }

        // 输出结果
        cout << ans << endl;
    }

    return 0;
}

时空复杂度

时间复杂度:O(N)。仅需一次遍历数组。

空间复杂度:O(1)。仅需若干常数变量。

华为OD算法/大厂面试高频题算法练习冲刺训练

  • 华为OD算法/大厂面试高频题算法冲刺训练目前开始常态化报名!目前已服务100+同学成功上岸!

  • 课程讲师为全网50w+粉丝编程博主@吴师兄学算法 以及小红书头部编程博主@闭着眼睛学数理化

  • 每期人数维持在20人内,保证能够最大限度地满足到每一个同学的需求,达到和1v1同样的学习效果!

  • 60+天陪伴式学习,40+直播课时,300+动画图解视频,300+LeetCode经典题,200+华为OD真题/大厂真题,还有简历修改、模拟面试、专属HR对接将为你解锁

  • 可上全网独家的欧弟OJ系统练习华子OD、大厂真题

  • 可查看链接 大厂真题汇总 & OD真题汇总(持续更新)

  • 绿色聊天软件戳 od1336了解更多

你可能感兴趣的:(最新华为OD真题,#,滑动窗口,算法,华为od)