简体   繁体   中英

To Find Vowel-Substring From a String

I have a string of lowercase English letters and an integer of the substring length. I have to find the substring of that length that contains the most vowels.

Example:

s = 'azerdii'

k = 5

The possible 5 character substrings are:

  1. 'azerd' No. of vowels = 2
  2. 'zerdi' No. of vowels = 2
  3. 'erdii' No. of vowels = 3

So the answer should be 'erdii'

Here is my code:

def findSubstring(s, k):
    i = 0
    lst = []
    count = 0
    tempL = []
    
    while(i != len(s)):
        a = i+k
        temp = s[i:a]
        lst.append(temp)
        if a != len(s):
            i+=1
        else:
            break
    
    for word in lst:
        for alphabet in word:
            if alphabet in 'aeiou':
                count += 1
        tempL.append(count)
    print(lst)
    print(tempL)
    return 

s = input()

k = int(input().strip())

print(findSubstring(s, k))

I'm getting 

['azerd', 'zerdi', 'erdii']
[2, 4, 7]

But the count should be

[2, 2, 3]

Please forgive any stupid errors I may have. I will certainly appreciate any help.

Try the following:

def find_substr(s, k):
    substrings = [s[i:i+k] for i in range(len(s) - k + 1)] # list of substrings
    # vowels = [sum(c in 'aeiou' for c in s) for s in substrings]
    # print(vowels) # [2, 2, 3]
    return max(substrings, key=lambda s: sum(c in 'aeiou' for c in s))

print(find_substr('azerdii', 5)) # 'erdii'

If you un-comment the lines that are commented out, you will see the number of vowels is correctly computed as [2, 2, 3] .


Here, sum(c in 'aeiou' for c in s) gets the number of vowels in a string s , which is equivalent to

count = 0
for alphabet in word:
    if alphabet in 'aeiou':
        count += 1

which in turn is the same as your code, except the line count = 0 . After processing each word , you need to reset count . So try adding count = 0 in your code.

You need to reset the count=0 at line number 17.

Try this code

def findSubstring(s, k):
    i = 0
    lst = []
    count = 0
    tempL = []
    
    while(i != len(s)):
        a = i+k
        temp = s[i:a]
        lst.append(temp)
        if a != len(s):
            i+=1
        else:
            break
    
    for word in lst:
        count = 0
        for alphabet in word:
            if alphabet in 'aeiou':
                count += 1
        tempL.append(count)
    print(lst)
    print(tempL)
    return 

s = 'azerdii'
k = 5
print(findSubstring(s, k))

You could use a sliding window approach, for an optimal time complexity single-pass solution:

def find_substring_length_k_most_vowels(s: str, k: int) -> str:
    '''Returns any substring of length k that has the max number of vowels.'''
    vowels = set('aeiou')
    max_vowel_count = curr_vowel_count = 0
    max_window_start, max_window_end = 0, -1
    window_start = 0
    for window_end, ch in enumerate(s):
        if ch in vowels:
            curr_vowel_count += 1
        if window_end - window_start + 1 == k:
            if curr_vowel_count > max_vowel_count:
                max_vowel_count = curr_vowel_count
                max_window_start, max_window_end = window_start, window_end
            curr_vowel_count -= 1 if s[window_start] in vowels else 0
            window_start += 1
    return s[max_window_start:max_window_end + 1]


def main() -> None:
    s = 'azerdii'
    k = 5
    print(find_substring_length_k_most_vowels(s, k))


if __name__ == '__main__':
    main()

Output:

erdii

Brute Force Solution

Intuition :

  1. Initialize a set and push all the elements of the sub string in that set(knowing that the element is a vowel). When its sizes == 5(as there are 5 vowels in English alphabet) then increase the counter by 1 Approach :

  2. Make a function isVowel that return (1/true) when the passed character is a vowel otherwise (0/false).

  3. Initialize 2 for loop a. Outer loop running from 0 to word.size()(till the end of the string). b.Inner loop running from i to word.size()(till the end of the string).

  4. Now initialize a SET inside the outer for loop (as we don't want that the values of previous iteration to persist in it).

  5. In the inner for loop initialize a condition that if the J th Character value is not a vowel then break the loop.

  6. And if it is a vowel then insert it in the initailzed SET

  7. Now again initialize a condition that if the size of SET is == 5 then increase the counter by 1.

  8. At last return the counter. Code:

     // Function that checks that the given character is a vowel or not int isVowel(char c) { if ((c == 'a') || (c == 'e') || (c == 'i') || (c == 'o') || (c == 'u')) { return 1; } return 0; } int countVowelSubstrings(string word) { int counter = 0; // initalize the counter with 0 for (int i = 0; i < word.size(); i++) { set<char> temp;// set initalized outside the for loop so as to avoid // the persitance of the pervious iteration values in //the set for (int j = i; j < word.size(); j++) { // if the jth charcter is not a vowel then break the loop if (isVowel(word[j]) == 0) { break; } // else insert the char value in the SET temp.insert(word[j]); // if size == 5 (as there are 5 vowels in English alphabet) then // increase the counter by 1 if (temp.size() == 5) { counter++; } } } return counter; } // Code By Ambuj Kumar

An almost one-liner functional approach:

from functools import reduce

def getVowelsLength(word, k):
    chunks = [word[i:i+k] for i in range(len(word)-(k-1))]
    return reduce(lambda x, y: x if x[1] > y[1] else y, list(zip(chunks, [sum(1 for l in w if l in 'aeiou') for w in chunks])))

which will give the correct answer: ('erdii', 3)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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