A string s
is nice if, for every letter of the alphabet that s
contains, it appears both in uppercase and lowercase. For example, "abABB"
is nice because 'A'
and 'a'
appear, and 'B'
and 'b'
appear. However, "abA"
is not because 'b'
appears, but 'B'
does not.
Given a string s
, return the longest substring of s
that is nice. If there are multiple, return the substring of the earliest occurrence. If there are none, return an empty string.
Example 1:
Input: s = "YazaAay" Output: "aAa" Explanation: "aAa" is a nice string because 'A/a' is the only letter of the alphabet in s, and both 'A' and 'a' appear. "aAa" is the longest nice substring.
Example 2:
Input: s = "Bb" Output: "Bb" Explanation: "Bb" is a nice string because both 'B' and 'b' appear. The whole string is a substring.
Example 3:
Input: s = "c" Output: "" Explanation: There are no nice substrings.
Constraints:
1 <= s.length <= 100
s
consists of uppercase and lowercase English letters.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:
The brute force approach to finding the longest nice substring involves checking every possible substring within the main string. For each substring, we determine if it's 'nice' based on the given criteria. Finally, we keep track of the longest 'nice' substring we've found.
Here's how the algorithm would work step-by-step:
def longest_nice_substring_brute_force(input_string):
longest_nice_substring = ""
for substring_length in range(1, len(input_string) + 1):
for starting_index in range(len(input_string) - substring_length + 1):
substring = input_string[starting_index:starting_index + substring_length]
# Check if the current substring is "nice"
if is_nice(substring):
# Update the longest nice substring found so far
if len(substring) > len(longest_nice_substring):
longest_nice_substring = substring
return longest_nice_substring
def is_nice(substring):
for character in substring:
if 'a' <= character <= 'z':
# Check if the uppercase version exists
if character.upper() not in substring:
return False
elif 'A' <= character <= 'Z':
# Check if the lowercase version exists
if character.lower() not in substring:
return False
return True
The goal is to find the longest substring where for every uppercase letter, its lowercase counterpart is also present, and vice-versa. The clever idea is to divide the problem into smaller, easier subproblems whenever we find a character that breaks the 'nice' condition.
Here's how the algorithm would work step-by-step:
def longest_nice_substring(input_string):
string_length = len(input_string)
if string_length < 2:
return input_string
for index in range(string_length):
character = input_string[index]
if 'a' <= character <= 'z':
if character.upper() not in input_string:
break
elif 'A' <= character <= 'Z':
if character.lower() not in input_string:
break
else:
return input_string
longest_substring = ""
# Split the string and recursively check each part.
for substring in input_string.split(character):
current_longest = longest_nice_substring(substring)
if len(current_longest) > len(longest_substring):
longest_substring = current_longest
return longest_substring
Case | How to Handle |
---|---|
Empty string | Return an empty string immediately as there can be no substring. |
String of length 1 | Return an empty string, as a nice string must contain both upper and lower case versions of a character. |
String with all uppercase or all lowercase characters | Return an empty string, as there are no characters with both case versions present. |
String with non-alphabetic characters | The solution should either ignore these characters or consider them invalid, based on the problem constraints; we will assume the solution ignores them. |
Very long string (close to maximum string length) | Ensure the algorithm has reasonable time complexity (e.g., avoid exponential solutions) and doesn't cause stack overflow if using recursion. |
String with many overlapping nice substrings | The solution should correctly identify the longest one among potentially multiple valid substrings. |
String where the longest nice substring starts at the beginning or end | The solution must not miss the substring if it is located at the extreme ends of the input string. |
String with characters close to ASCII boundaries (e.g., 'A' or 'z') | Ensure the character case comparison handles edge character correctly without index out of bounds exception if using array of fixed size based on character values. |