算法题-Leetcode-所有子字符串中的元音

410 阅读2分钟

描述

给你一个字符串 word ,返回 word 的所有子字符串中 元音的总数 ,元音是指 'a'、'e'、'i'、'o' 和 'u' 。

子字符串 是字符串中一个连续(非空)的字符序列。

注意:由于对 word 长度的限制比较宽松,答案可能超过有符号 32 位整数的范围。计算时需当心。

示例:

输入:word = "aba" 输出:6 解释: 所有子字符串是:"a"、"ab"、"aba"、"b"、"ba" 和 "a" 。

  • "b" 中有 0 个元音
  • "a"、"ab"、"ba" 和 "a" 每个都有 1 个元音
  • "aba" 中有 2 个元音 因此,元音总数 = 0 + 1 + 1 + 1 + 1 + 2 = 6 。   提示:
  • 1 <= word.length <= 10^5
  • word 由小写英文字母组成

思路

失败的思路

这道题,我一开始的思路是用 dp数组记录所有元字母所在的下标,然后不断的比较以 两个元字母下标为边界(两个下标一直是则只有一个字母)向两边扩展,直到遇到其他元字母。统计两个元字母左右两边的非元字母个数,再计算得到包括边界在内的元字母个数。左右两边相乘得到有多少子串个数,再乘以边界内元字母个数,得到 这两个下标所在扩展得到的所有字符串中元音字母总数,但是这种方法,在遇到最后一个基本全是元音字母的10000长度的数据时超时了。这种方法复杂度 由字母串中,元音字母个数决定,所有最坏能达到O(n^2),

class Solution {
    public long countVowels(String word) {
        int len  = 0;
        int[] dp =new int[word.length()];
        char ch;
        long sum = 0;
        int count = 0;
        int leftNum,rightNum;
        for(int i = 0 ;i<word.length();i++){
            ch = word.charAt(i);
            if('a' == ch || 'e' == ch || 'i' == ch || 'o' == ch || 'u' == ch){
                dp[len++] = i;
            }
        }
        for(int i = 0; i< len;i++){
            for(int j = i;j<len;j++){
                count = j-i+1;
                if(i == 0){
                    leftNum = dp[i];
                }else{
                    leftNum = dp[i] - dp[i-1] - 1;
                }
                if(j == len - 1){
                    rightNum = word.length() - dp[j] -1;
                }else {
                    rightNum = dp[j+1] - dp[j] -1;
                }
                sum+= (leftNum+1)*(rightNum+1) * count;       
            }
        }
        return sum;
    }
}

改进后

后来思考了下,其实可以简化成O(n)算法,对于单个元字母而言,其实其只需要计算它在所有可能存在的子串的总数就可以了,不必考虑它所在的子串中可能含有的其他元字母,因为都只考虑自己,就不会产生重复计算某个字符中元字母个数的。 优化后代码

class Solution {
    public long countVowels(String word) {
        long sum = 0;
        long len = word.length();
        char ch;
        for(int i = 0 ;i<len;i++){
            ch = word.charAt(i);
            if('a' == ch || 'e' == ch || 'i' == ch || 'o' == ch || 'u' == ch){
                sum+= (i+1)*(len-i);// 每个字符只用考虑自己在所有字符串中可能中出现的次数即可,不必去思考一个字符串中有多少个字符
            }
        }
       
        return sum;
    }
}