Mutating counts without cleanup
Wrong move: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.
Build confidence with an intuition-first walkthrough focused on hash map fundamentals.
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 <= 100s consists of uppercase and lowercase English letters.Problem summary: 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.
Start with the most direct exhaustive search. That gives a correctness anchor before optimizing.
Pattern signal: Hash Map · Bit Manipulation · Sliding Window
"YazaAay"
"Bb"
"c"
number-of-good-paths)Source-backed implementations are provided below for direct study and interview prep.
// Accepted solution for LeetCode #1763: Longest Nice Substring
class Solution {
public String longestNiceSubstring(String s) {
int n = s.length();
int k = -1;
int mx = 0;
for (int i = 0; i < n; ++i) {
Set<Character> ss = new HashSet<>();
for (int j = i; j < n; ++j) {
ss.add(s.charAt(j));
boolean ok = true;
for (char a : ss) {
char b = (char) (a ^ 32);
if (!(ss.contains(a) && ss.contains(b))) {
ok = false;
break;
}
}
if (ok && mx < j - i + 1) {
mx = j - i + 1;
k = i;
}
}
}
return k == -1 ? "" : s.substring(k, k + mx);
}
}
// Accepted solution for LeetCode #1763: Longest Nice Substring
func longestNiceSubstring(s string) string {
n := len(s)
k, mx := -1, 0
for i := 0; i < n; i++ {
ss := map[byte]bool{}
for j := i; j < n; j++ {
ss[s[j]] = true
ok := true
for a := range ss {
b := a ^ 32
if !(ss[a] && ss[b]) {
ok = false
break
}
}
if ok && mx < j-i+1 {
mx = j - i + 1
k = i
}
}
}
if k < 0 {
return ""
}
return s[k : k+mx]
}
# Accepted solution for LeetCode #1763: Longest Nice Substring
class Solution:
def longestNiceSubstring(self, s: str) -> str:
n = len(s)
ans = ''
for i in range(n):
ss = set()
for j in range(i, n):
ss.add(s[j])
if (
all(c.lower() in ss and c.upper() in ss for c in ss)
and len(ans) < j - i + 1
):
ans = s[i : j + 1]
return ans
// Accepted solution for LeetCode #1763: Longest Nice Substring
/**
* [1763] Longest Nice Substring
*
* 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.
*
*/
pub struct Solution {}
// problem: https://leetcode.com/problems/longest-nice-substring/
// discuss: https://leetcode.com/problems/longest-nice-substring/discuss/?currentPage=1&orderBy=most_votes&query=
// submission codes start here
impl Solution {
pub fn longest_nice_substring(s: String) -> String {
let sb = s.as_bytes();
let mut max_range: (usize, usize) = (0, 0);
for i in 0..(s.len() - 1) {
let (mut lower_mask, mut upper_mask) = (0u32, 0u32);
for j in i..s.len() {
match sb[j] >= b'a' {
true => lower_mask |= 1 << (sb[j] - b'a'),
false => upper_mask |= 1 << (sb[j] - b'A'),
};
if lower_mask == upper_mask && (j + 1 - i) > (max_range.1 - max_range.0) {
max_range = (i, j + 1);
}
}
}
String::from_utf8(sb[max_range.0..max_range.1].to_vec()).unwrap()
}
}
// submission codes end
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1763_example_1() {
let s = "YazaAay".to_string();
let result = "aAa".to_string();
assert_eq!(Solution::longest_nice_substring(s), result);
}
#[test]
fn test_1763_example_2() {
let s = "Bb".to_string();
let result = "Bb".to_string();
assert_eq!(Solution::longest_nice_substring(s), result);
}
#[test]
fn test_1763_example_3() {
let s = "c".to_string();
let result = "".to_string();
assert_eq!(Solution::longest_nice_substring(s), result);
}
}
// Accepted solution for LeetCode #1763: Longest Nice Substring
function longestNiceSubstring(s: string): string {
const n = s.length;
let ans = '';
for (let i = 0; i < n; i++) {
let lower = 0,
upper = 0;
for (let j = i; j < n; j++) {
const c = s.charCodeAt(j);
if (c > 96) {
lower |= 1 << (c - 97);
} else {
upper |= 1 << (c - 65);
}
if (lower == upper && j - i + 1 > ans.length) {
ans = s.substring(i, j + 1);
}
}
}
return ans;
}
Use this to step through a reusable interview workflow for this problem.
Sort the array in O(n log n), then scan for the missing or unique element by comparing adjacent pairs. Sorting requires O(n) auxiliary space (or O(1) with in-place sort but O(n log n) time remains). The sort step dominates.
Bitwise operations (AND, OR, XOR, shifts) are O(1) per operation on fixed-width integers. A single pass through the input with bit operations gives O(n) time. The key insight: XOR of a number with itself is 0, which eliminates duplicates without extra space.
Review these before coding to avoid predictable interview regressions.
Wrong move: Zero-count keys stay in map and break distinct/count constraints.
Usually fails on: Window/map size checks are consistently off by one.
Fix: Delete keys when count reaches zero.
Wrong move: Using `if` instead of `while` leaves the window invalid for multiple iterations.
Usually fails on: Over-limit windows stay invalid and produce wrong lengths/counts.
Fix: Shrink in a `while` loop until the invariant is valid again.