The beauty of a string is the difference in frequencies between the most frequent and least frequent characters.
"abaacc"
is 3 - 1 = 2
.Given a string s
, return the sum of beauty of all of its substrings.
Example 1:
Input: s = "aabcb" Output: 5 Explanation: The substrings with non-zero beauty are ["aab","aabc","aabcb","abcb","bcb"], each with beauty equal to 1.
Example 2:
Input: s = "aabcbaa" Output: 17
Constraints:
1 <= s.length <= 500
s
consists of only lowercase English letters.This problem asks to calculate the sum of beauty values for all substrings of a given string. The beauty of a string is defined as the absolute difference between the maximum and minimum frequencies of its characters.
There are two main approaches to solve this problem:
Approach 1: Enumeration and Counting
This approach iterates through all possible substrings and counts the frequency of each character in each substring. Then, it calculates the beauty of the substring and adds it to the total sum.
Algorithm:
ans
to 0. This variable will store the total sum of beauty values.i
of the string.i
, iterate through each ending index j
from i
to the end of the string. This generates all substrings starting at i
.max_freq - min_freq
.ans
.ans
.Time Complexity: O(n^3), where n is the length of the string. This is because there are O(n^2) substrings, and for each substring, we need O(n) time to count character frequencies in the worst case.
Space Complexity: O(n) in the worst case to store the frequency counter for a substring. (Could be reduced to O(1) if using a fixed size array for the alphabet).
Approach 2: Optimized Counting
This approach improves upon the first approach by optimizing the frequency counting. It maintains a frequency map and updates it incrementally as we move from one substring to the next.
Algorithm:
ans
to 0.i
of the string.cnt
and a frequency of frequencies counter freq
. freq
counts how many characters have each frequency.j
from i
to the end of the string.freq
for its current frequency and increment it for the new frequency (after adding 1).mi
(the smallest frequency with a count > 0) and the maximum frequency mx
.mx - mi
and add it to ans
.ans
.Time Complexity: O(n^2), where n is the length of the string. This is because there are O(n^2) substrings, and for each substring, updating the frequency counters takes constant time on average.
Space Complexity: O(1), assuming the alphabet size is constant (26 in this case).
The code examples in the problem description demonstrate both approaches. Approach 1 is simpler to understand but less efficient. Approach 2 is more complex but significantly faster. The complexities stated above are for Approach 1. Approach 2 has a time complexity of O(n^2). Both are given in multiple programming languages. Note that the constant factors and actual performance will vary depending on language, implementation details and input data. The Python3 example below is using the collections.Counter
object which handles frequency counting efficiently.
Python3 (Approach 1 - less efficient):
from collections import Counter
class Solution:
def beautySum(self, s: str) -> int:
ans, n = 0, len(s)
for i in range(n):
cnt = Counter()
for j in range(i, n):
cnt[s[j]] += 1
ans += max(cnt.values()) - min(cnt.values()) if len(cnt) > 0 else 0 #Handle empty substring case.
return ans
Python3 (Approach 2 - more efficient):
from collections import Counter
class Solution:
def beautySum(self, s: str) -> int:
ans, n = 0, len(s)
for i in range(n):
cnt = Counter()
freq = Counter()
mi = mx = 1
for j in range(i, n):
freq[cnt[s[j]]] -= 1
cnt[s[j]] += 1
freq[cnt[s[j]]] += 1
if cnt[s[j]] == 1:
mi = 1
if freq[mi] == 0:
mi += 1
if cnt[s[j]] > mx:
mx = cnt[s[j]]
ans += mx - mi
return ans
The other language examples in the problem description follow a similar structure to these Python examples, reflecting the two approaches. Remember to choose the appropriate approach based on the performance requirements of your application. For larger inputs, Approach 2 will be significantly faster.