繁体   English   中英

如何使用 java 计算给定字符串的 substring 中的总元音?

[英]How to count the total vowels in substring of a given string using java?

给你一个字符串,一个必须构成给定字符串的所有 substring,

例如,给出字符串“baceb”,子字符串是 {b, ba, bac, bace, a, ac, ace, aceb, c, ce, ceb, e, eb, baceb} 并且列表中的每个元素都包含,{ 0, 1, 1, 2, 1, 1, 2, 2, 0, 1, 1, 1, 1, 2} 个元音,总和为 16。字符串的大小可达 10^5。

这就是我已经走了多远,适用于较小的案例文件,对于较大的案例,我得到超时错误。

    Scanner sc=new Scanner(System.in);
    int n=sc.nextInt();
    sc.nextLine();

    while(n-->0){
        ArrayList<String> list=new ArrayList<>();
        String s=sc.nextLine();
        int len=s.length();
        s=s.toLowerCase();
        for(int i=0;i<len;i++){
            for(int j=i+1;j<=len;j++){
                String temp=s.substring(i,j);
                if(!list.contains(temp)){
                    list.add(temp);
                }
            }
        }

    // System.out.println(list);
    int count=0;
    for(String str:list){
        for(int k=0;k<str.length();k++){
            char ch=str.charAt(k);
            if(ch=='a'||ch=='e'||ch=='i'||ch=='o'||ch=='u'){
                count++;
            }
        }
    }
    System.out.println(count);
    }

n 是测试用例的数量。

任何帮助表示赞赏。 谢谢。

到目前为止,您已经正确地完成了所有操作。 你需要做更多。

编程任务的第一种方法是编写清晰的代码来解决它。 在这种情况下,编写代码来生成子字符串并计算生成的子字符串中的元音。 每个程序员都可以理解这一点。 非常好的工作。

接下来,如果编码解决方案的性能不够好,就该进行优化了(对于 99.9% 的实际编程,我们永远不会达到这一点,但在像您这样的编码挑战中,这是司空见惯的)。 您将需要性能足够好的代码,不会发生超时错误。

对于优化的解决方案,我们不需要生成子字符串。 相反,我们观察到:对于您的示例字符串,长度为 5 个字符:第一个字符(索引 0)可以是 5 个子字符串的一部分: bbabacbacebaceb 然而,它是一个辅音,所以多少并不重要。 下一个字符,索引 1 处a ,是 8 个子串的一部分:4 个从索引 0 开始,4 个从索引 1 开始。因此,它在所有子串的 16 个元音中贡献了 8 个。 如果下一个字符(索引 2 处的c )是元音,我们需要计算它进入 9 个子字符串:3 从索引 0 开始,3 从索引 1 开始,3 从索引 2 开始。你能开始看到一种模式? 我认为我们可以通过将直到并包括该字符的字符数乘以从该字符到字符串末尾的字符数来计算字符贡献的子字符串数。 请检查我是否正确。

所以一个有效的算法可以是:遍历字符串索引。 如果给定索引处的字符是元音,计算它有多少子串,并将这个计数加到总数中。

编辑:

但是如果不构建 substring,如何知道 substring 中实际有多少元音?

我不确定如何比我已经尝试过的更好地解释这一点。

关键是:您不需要知道每个 substring 中有多少个元音。 您只需要知道所有这些计数的总和 因此,我们以完全不同的方式获得该总和。 我们正在利用这样一个事实,即每次 substring 中有元音时,该元音必须来自原始字符串中的一个特定索引。 因此,我们不是计算每个 substring 中的元音,而是计算每个元音所在的子串。结果必须相同。

从您的问题baceb中获取示例字符串。 有两个元音, a在索引 1 和e在索引 3。a a子串babacbacebacebaacaceaceb中,总共 8 个。 所以对所有子串中的元音计数贡献了 8。 e也在 8 个子串中。 8 + 8 等于 16,这是所有子串中元音计数的总和。

让我尝试一个更正式的论点。 考虑长度为len ( 0 <= i < len ) 的字符串中索引i处的元音。 现在的问题是:在字符串的子字符串中,这个特定的元音包含多少? 要将其包含在 substring 中,substring 必须位于索引 0、1、... i (含)处,因此有i + 1可能的起始索引。 substring 必须以索引i + 1i + 2 ,... len结束,从而提供len - i可能性。 由于每个可能的开始索引都可以与任何可能的结束索引组合来定义 substring,我们可以将这两个数字相乘。 该乘积给出了这个元音所在的子串的数量。因此,这个元音对所有子串中元音计数总和的贡献。 所以剩下要做的就是将原始字符串中元音的所有乘积相加。 然后你就得到了你的结果。

快乐编码。

PS我假设子字符串不必是唯一的。 在字符串bobo中,substring bo出现两次, o两次都有助于元音计数。 我从您的代码中看到这与您的理解不一致,但我仍然认为我的代码是正确的。

PPS 另请注意,对于长度不超过 100 000 的字符串,总数可能会溢出int 使用long作为总计数。

PPPS 对于额外的轻微优化,您可以更快地检查字符是否为元音。 一次创建一个BitSet ,并设置每个元音的大小写变体对应的 10 位。 现在要检查一个字符是否为元音,只需查询BitSet中的相应位是否已设置。 无需先转换为小写。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM