A string s
is called happy if it satisfies the following conditions:
s
only contains the letters 'a'
, 'b'
, and 'c'
.s
does not contain any of "aaa"
, "bbb"
, or "ccc"
as a substring.s
contains at most a
occurrences of the letter 'a'
.s
contains at most b
occurrences of the letter 'b'
.s
contains at most c
occurrences of the letter 'c'
.Given three integers a
, b
, and c
, return the longest possible happy string. If there are multiple longest happy strings, return any of them. If there is no such string, return the empty string ""
.
A substring is a contiguous sequence of characters within a string.
Example 1:
Input: a = 1, b = 1, c = 7 Output: "ccaccbcc" Explanation: "ccbccacc" would also be a correct answer.
Example 2:
Input: a = 7, b = 1, c = 0 Output: "aabaa" Explanation: It is the only correct answer in this case.
Constraints:
0 <= a, b, c <= 100
a + b + c > 0
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:
To find the longest possible string without any triple letters, the brute force approach is to build every single possible string using the letters we have. After creating all combinations, we check each one to see if it follows the 'no three in a row' rule and then pick the longest one that does.
Here's how the algorithm would work step-by-step:
def longestHappyString(a_count: int, b_count: int, c_count: int) -> str:
all_possible_happy_strings = []
def generate_strings(current_string, remaining_a, remaining_b, remaining_c):
# A string is a candidate for the final list once we've exhausted one or more characters.
if len(current_string) > 1:
all_possible_happy_strings.append(current_string)
# Explore adding 'a' if it's available and doesn't create 'aaa'.
if remaining_a > 0 and not current_string.endswith('aa'):
generate_strings(current_string + 'a', remaining_a - 1, remaining_b, remaining_c)
# Explore adding 'b' if it's available and doesn't create 'bbb'.
if remaining_b > 0 and not current_string.endswith('bb'):
generate_strings(current_string + 'b', remaining_a, remaining_b - 1, remaining_c)
# Explore adding 'c' if it's available and doesn't create 'ccc'.
if remaining_c > 0 and not current_string.endswith('cc'):
generate_strings(current_string + 'c', remaining_a, remaining_b, remaining_c - 1)
generate_strings("", a_count, b_count, c_count)
longest_string_found = ""
for candidate_string in all_possible_happy_strings:
if len(candidate_string) > len(longest_string_found):
longest_string_found = candidate_string
# After checking all generated happy strings, return the one with the maximum length.
return longest_string_found
The best way to build the longest possible string without having three identical characters in a row is to be greedy. At each step, we'll add the character we have the most of, but we'll be careful not to add it if it would break the rule.
Here's how the algorithm would work step-by-step:
import heapq
def longestDiverseString(a, b, c):
result_list = []
max_heap = []
if a > 0:
heapq.heappush(max_heap, (-a, 'a'))
if b > 0:
heapq.heappush(max_heap, (-b, 'b'))
if c > 0:
heapq.heappush(max_heap, (-c, 'c'))
while max_heap:
count, character = heapq.heappop(max_heap)
# If adding this character would create three in a row, we must use a different one.
if len(result_list) >= 2 and result_list[-1] == character and result_list[-2] == character:
# If no other characters are available, we must stop to avoid breaking the rule.
if not max_heap:
break
second_count, second_character = heapq.heappop(max_heap)
result_list.append(second_character)
second_count += 1
if second_count < 0:
heapq.heappush(max_heap, (second_count, second_character))
heapq.heappush(max_heap, (count, character)) # Put the original most frequent back.
else:
result_list.append(character)
count += 1
if count < 0:
heapq.heappush(max_heap, (count, character))
return "".join(result_list)
Case | How to Handle |
---|---|
All counts are zero (a=0, b=0, c=0) | The algorithm should correctly produce an empty string as no characters are available to use. |
One or two of the counts are zero (e.g., a=5, b=0, c=0) | The solution should build a string of length 2 (e.g., "aa") and then stop, as no other characters are available to break the consecutive sequence. |
Highly skewed distribution of counts (e.g., a=100, b=1, c=1) | The greedy approach must be able to handle this by using the rare characters to break up long sequences of the most frequent character (e.g., "aabaacaa..."). |
All counts are equal (e.g., a=3, b=3, c=3) | The algorithm should alternate between the characters to produce a balanced string like "aabbaacc..." or "abcabc...". |
One count is much larger than the sum of the other two (e.g., a=7, b=1, c=1) | The solution should use at most two of the dominant character, followed by one of the others, until the less frequent ones are exhausted (e.g., "aabaacaa"). |
Inputs are the minimum possible non-zero values (e.g., a=1, b=1, c=0) | The solution should correctly form a simple valid string like "ab" or "ba" by using the available characters. |
Input counts are very large, nearing language-specific integer limits | The solution should use data types that can handle large numbers, and the iterative string-building process must be memory-efficient. |
The problem constraints guarantee non-negative inputs (a, b, c >= 0) | The solution does not need to handle negative inputs, but it should be robust enough to work with zero counts as specified. |