class Solution:
def longestNiceSubstring(self, s: str) -> str:
def is_nice(sub):
chars = set(sub)
for c in chars:
if c.swapcase() not in chars:
return False
return True
max_sub = ""
n = len(s)
for i in range(n):
for j in range(i+1, n+1):
sub = s[i:j]
if is_nice(sub) and len(sub) > len(max_sub):
max_sub = sub
return max_sub
class Solution {
public:
string longestNiceSubstring(string s) {
int maxLen = 0, start = 0;
int n = s.size();
auto isNice = [](const string& sub) {
unordered_set<char> chars(sub.begin(), sub.end());
for (char c : chars) {
if (chars.count(islower(c) ? toupper(c) : tolower(c)) == 0)
return false;
}
return true;
};
for (int i = 0; i < n; ++i) {
for (int j = i + 1; j <= n; ++j) {
string sub = s.substr(i, j - i);
if (isNice(sub) && (j - i) > maxLen) {
maxLen = j - i;
start = i;
}
}
}
return s.substr(start, maxLen);
}
};
class Solution {
public String longestNiceSubstring(String s) {
int maxLen = 0, start = 0;
int n = s.length();
for (int i = 0; i < n; ++i) {
for (int j = i + 1; j <= n; ++j) {
String sub = s.substring(i, j);
if (isNice(sub) && (j - i) > maxLen) {
maxLen = j - i;
start = i;
}
}
}
return s.substring(start, start + maxLen);
}
private boolean isNice(String sub) {
Set<Character> chars = new HashSet<>();
for (char c : sub.toCharArray()) {
chars.add(c);
}
for (char c : chars) {
if (!chars.contains(Character.isLowerCase(c) ? Character.toUpperCase(c) : Character.toLowerCase(c))) {
return false;
}
}
return true;
}
}
var longestNiceSubstring = function(s) {
function isNice(sub) {
let chars = new Set(sub);
for (let c of chars) {
if (!chars.has(
c === c.toLowerCase() ? c.toUpperCase() : c.toLowerCase()
)) {
return false;
}
}
return true;
}
let maxSub = "";
for (let i = 0; i < s.length; ++i) {
for (let j = i + 1; j <= s.length; ++j) {
let sub = s.slice(i, j);
if (isNice(sub) && sub.length > maxSub.length) {
maxSub = sub;
}
}
}
return maxSub;
};
Given a string s
, find the longest substring of s
such that for every character in the substring, both its uppercase and lowercase forms also appear in the substring. Such a substring is called "nice". If there are multiple longest nice substrings, return the one that appears first. If there is no nice substring, return an empty string.
s
are English letters.s
.The problem asks for the longest substring where every character's uppercase and lowercase forms are both present. At first, it's tempting to check every possible substring, but that would be inefficient for large strings.
The brute-force approach is to consider all substrings and check if each is "nice". However, this is slow because the number of substrings grows quadratically with the length of s
.
To optimize, we need a way to quickly check if a substring is "nice", and possibly avoid checking substrings that cannot possibly be nice (for example, if a character only appears in one case). However, since the constraints are modest (string length up to 100), the brute-force approach is acceptable and simple to implement.
s
. For each starting index i
, and ending index j
, consider the substring s[i:j]
.We use sets for quick character existence checking, which is O(1) per check. The double loop ensures all substrings are considered, and the check for "niceness" is linear in the length of the substring.
Consider s = "YazaAay"
.
The algorithm checks all substrings and updates the result whenever a longer nice substring is found.
The key insight is that a "nice" substring must contain both cases for every letter present. By checking all possible substrings and verifying this property using a set for fast lookups, we can find the longest nice substring efficiently for small input strings. The brute-force approach is clear and effective given the constraints, and the solution is easy to implement in multiple languages.