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:
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 :
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 :
Make a function isVowel that return (1/true) when the passed character is a vowel otherwise (0/false).
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).
Now initialize a SET inside the outer for loop (as we don't want that the values of previous iteration to persist in it).
In the inner for loop initialize a condition that if the J th Character value is not a vowel then break the loop.
And if it is a vowel then insert it in the initailzed SET
Now again initialize a condition that if the size of SET is == 5 then increase the counter by 1.
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.