You are given a string s
consisting of digits from '1'
to '9'
and two positive integers num1
and num2
.
A substring of s
is considered good if its length is divisible by num1
and the ratio of its first num1
characters' numerical product to its last num1
characters' numerical product is equal to num2
.
num1 = 2
, then a good substring "123456"
has a length divisible by 2
and the product of its first 2
characters (1 * 2 = 2
) divided by the product of its last 2
characters (5 * 6 = 30
) is equal to num2
.Return the number of good substrings of s
.
Note that:
1
.Example 1:
Input: s = "2358132", num1 = 1, num2 = 3 Output: 3 Explanation: There are 3 good substrings: - s[0...0] = "2". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 2. The product of its last num1 = 1 characters is 2. The ratio is 2 / 2 = 1 != num2 = 3. - s[2...2] = "5". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 5. The product of its last num1 = 1 characters is 5. The ratio is 5 / 5 = 1 != num2 = 3. - s[3...3] = "8". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 8. The product of its last num1 = 1 characters is 8. The ratio is 8 / 8 = 1 != num2 = 3. - s[0...1] = "23". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 2. The product of its last num1 = 1 characters is 3. The ratio is 2 / 3 != num2 = 3. - s[0...2] = "235". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 2. The product of its last num1 = 1 characters is 5. The ratio is 2 / 5 != num2 = 3. - s[0...3] = "2358". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 2. The product of its last num1 = 1 characters is 8. The ratio is 2 / 8 != num2 = 3. - s[0...4] = "23581". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 2. The product of its last num1 = 1 characters is 1. The ratio is 2 / 1 != num2 = 3. - s[0...5] = "235813". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 2. The product of its last num1 = 1 characters is 3. The ratio is 2 / 3 != num2 = 3. - s[0...6] = "2358132". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 2. The product of its last num1 = 1 characters is 2. The ratio is 2 / 2 = 1 != num2 = 3. - s[1...1] = "3". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 3. The product of its last num1 = 1 characters is 3. The ratio is 3 / 3 = 1 != num2 = 3. - s[1...2] = "35". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 3. The product of its last num1 = 1 characters is 5. The ratio is 3 / 5 != num2 = 3. - s[1...3] = "358". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 3. The product of its last num1 = 1 characters is 8. The ratio is 3 / 8 != num2 = 3. - s[1...4] = "3581". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 3. The product of its last num1 = 1 characters is 1. The ratio is 3 / 1 != num2 = 3. - s[1...5] = "35813". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 3. The product of its last num1 = 1 characters is 3. The ratio is 3 / 3 = 1 != num2 = 3. - s[1...6] = "358132". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 3. The product of its last num1 = 1 characters is 2. The ratio is 3 / 2 != num2 = 3. - s[2...2] = "5". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 5. The product of its last num1 = 1 characters is 5. The ratio is 5 / 5 = 1 != num2 = 3. - s[2...3] = "58". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 5. The product of its last num1 = 1 characters is 8. The ratio is 5 / 8 != num2 = 3. - s[2...4] = "581". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 5. The product of its last num1 = 1 characters is 1. The ratio is 5 / 1 != num2 = 3. - s[2...5] = "5813". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 5. The product of its last num1 = 3. The ratio is 5 / 3 != num2 = 3. - s[2...6] = "58132". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 5. The product of its last num1 = 2. The ratio is 5 / 2 != num2 = 3. - s[3...3] = "8". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 8. The product of its last num1 = 8. The ratio is 8 / 8 = 1 != num2 = 3. - s[3...4] = "81". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 8. The product of its last num1 = 1. The ratio is 8 / 1 != num2 = 3. - s[3...5] = "813". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 8. The product of its last num1 = 3. The ratio is 8 / 3 != num2 = 3. - s[3...6] = "8132". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 8. The product of its last num1 = 2. The ratio is 8 / 2 != num2 = 3. - s[4...4] = "1". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 1. The product of its last num1 = 1. The ratio is 1 / 1 != num2 = 3. - s[4...5] = "13". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 1. The product of its last num1 = 3. The ratio is 1 / 3 != num2 = 3. - s[4...6] = "132". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 1. The product of its last num1 = 2. The ratio is 1 / 2 != num2 = 3. - s[5...5] = "3". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 3. The product of its last num1 = 3. The ratio is 3 / 3 = 1 != num2 = 3. - s[5...6] = "32". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 3. The product of its last num1 = 2. The ratio is 3 / 2 != num2 = 3. - s[6...6] = "2". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 2. The product of its last num1 = 2. The ratio is 2 / 2 = 1 != num2 = 3. None of the substrings are good.
Example 2:
Input: s = "1326", num1 = 2, num2 = 1 Output: 1 Explanation: There is 1 good substring: - s[0...3] = "1326". Its length is divisible by num1 = 2. The product of its first num1 = 2 characters is 1 * 3 = 3. The product of its last num1 = 2 characters is 2 * 6 = 12. The ratio is 3 / 12 != num2 = 1. - s[0...1] = "13". Its length is divisible by num1 = 2 is false - s[1...2] = "32". Its length is divisible by num1 = 2 is false - s[2...3] = "26". Its length is divisible by num1 = 2 is false Substring [0...3] is invalid because 3/12 != 1.
Example 3:
Input: s = "95145", num1 = 1, num2 = 1 Output: 5 Explanation: There are 5 good substrings: - s[0...0] = "9". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 9. The product of its last num1 = 1 characters is 9. The ratio is 9 / 9 = 1 == num2 = 1. - s[1...1] = "5". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 5. The product of its last num1 = 1 characters is 5. The ratio is 5 / 5 = 1 == num2 = 1. - s[2...2] = "1". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 1. The product of its last num1 = 1 characters is 1. The ratio is 1 / 1 = 1 == num2 = 1. - s[3...3] = "4". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 4. The product of its last num1 = 4. The ratio is 4 / 4 = 1 == num2 = 1. - s[4...4] = "5". Its length is divisible by num1 = 1. The product of its first num1 = 1 characters is 5. The product of its last num1 = 5. The ratio is 5 / 5 = 1 == num2 = 1.
Constraints:
1 <= s.length <= 105
s[i]
is a digit from '1'
to '9'
.1 <= num1 <= s.length / 2
1 <= num2 <= 20
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
We need to find specific sections within a larger piece of text that meet a defined ratio. The brute force strategy checks every possible section to see if it matches the ratio. It's like examining every possible piece of tape from a roll, one by one, to see if its length is correct in relation to its width.
Here's how the algorithm would work step-by-step:
def number_of_substrings_with_fixed_ratio(main_string, first_character, second_character, required_ratio):
number_of_substrings = 0
for start_index in range(len(main_string)): # Iterate through possible start indices
for end_index in range(start_index, len(main_string)): # Iterate through possible end indices
substring = main_string[start_index:end_index+1]
first_character_count = 0
second_character_count = 0
for char in substring:
if char == first_character:
first_character_count += 1
elif char == second_character:
second_character_count += 1
# Avoid division by zero
if second_character_count == 0:
if first_character_count == 0 and required_ratio == 0:
number_of_substrings += 1
elif first_character_count > 0 and float('inf') == required_ratio:
number_of_substrings +=1
continue
current_ratio = first_character_count / second_character_count
# Key decision point, checks required ratio
if current_ratio == required_ratio:
number_of_substrings += 1
return number_of_substrings
The most efficient solution avoids checking every single substring. It focuses on tracking the counts of two different values and using those counts to quickly identify substrings that match the desired ratio.
Here's how the algorithm would work step-by-step:
def number_of_substrings_with_fixed_ratio(input_string, ratio_numerator, ratio_denominator):
running_total = 0
substring_count = 0
running_total_counts = {0: 1}
for character in input_string:
# Calculate prefix sum based on character
if character == '1':
running_total += ratio_denominator
else:
running_total -= ratio_numerator
#If the prefix sum already exists, increment the substring count
if running_total in running_total_counts:
substring_count += running_total_counts[running_total]
running_total_counts[running_total] += 1
else:
running_total_counts[running_total] = 1
return substring_count
Case | How to Handle |
---|---|
Empty string s | Return 0 immediately as no substrings can exist. |
num2 is zero | Check if num2 is zero, if so, either return all substrings with zero occurrences of num1 (if num1 is zero as well) or return 0 (if num1 is non-zero) to avoid division by zero and handle invalid ratios. |
String 's' containing only num1 | Iterate through all possible substring lengths and check the ratio condition, accounting for possible multiple valid substrings. |
String 's' containing only num2 | Iterate through all possible substring lengths and check the ratio condition, accounting for possible multiple valid substrings. |
Large string 's' causing potential integer overflow if counts are not handled carefully. | Use long or appropriate data types to store the counts to avoid integer overflows. |
num1 and num2 are the same value. | The condition simplifies to counting substrings where occurrences of num1 are equal to the occurrences of itself, which is every substring containing num1. |
String 's' does not contain num1 or num2 at all. | If num1 and num2 are not present, and num2 is not zero return 0; otherwise if num2 is 0 check for when num1 is also 0 and if it is, all substrings are valid. |
String 's' contains characters that are not num1 or num2. | The counts of num1 and num2 should only consider substrings consisting of num1 and num2 values, effectively ignoring other characters. |