website/content.en/ChapterFour/1700~1799/1763.Longest-Nice-Substring.md
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.When, for every type of letter contained in a string s, both its uppercase and lowercase forms appear in s, this string s is called a nice string. For example, "abABB" is a nice string because 'A' and 'a' both appear, and 'B' and 'b' also both appear. However, "abA" is not a nice string because 'b' appears, but 'B' does not.
Given a string s, return the longest nice substring of s. If there are multiple answers, return the one that appears earliest. If no nice substring exists, return an empty string.
i as the split point to split the string in order. Determine separately whether the left and right strings satisfy the definition of a nice string. The separated left and right strings can continue to be divided. Continue until only one letter remains. Record the earliest occurring string during this process.package leetcode
import "unicode"
// Solution 1: divide and conquer, time complexity O(n)
func longestNiceSubstring(s string) string {
if len(s) < 2 {
return ""
}
chars := map[rune]int{}
for _, r := range s {
chars[r]++
}
for i := 0; i < len(s); i++ {
r := rune(s[i])
_, u := chars[unicode.ToUpper(r)]
_, l := chars[unicode.ToLower(r)]
if u && l {
continue
}
left := longestNiceSubstring(s[:i])
right := longestNiceSubstring(s[i+1:])
if len(left) >= len(right) {
return left
} else {
return right
}
}
return s
}
// Solution 2: use binary to represent state
func longestNiceSubstring1(s string) (ans string) {
for i := range s {
lower, upper := 0, 0
for j := i; j < len(s); j++ {
if unicode.IsLower(rune(s[j])) {
lower |= 1 << (s[j] - 'a')
} else {
upper |= 1 << (s[j] - 'A')
}
if lower == upper && j-i+1 > len(ans) {
ans = s[i : j+1]
}
}
}
return
}
// Solution 3: brute-force enumeration, time complexity O(n^2)
func longestNiceSubstring2(s string) string {
res := ""
for i := 0; i < len(s); i++ {
m := map[byte]int{}
m[s[i]]++
for j := i + 1; j < len(s); j++ {
m[s[j]]++
if checkNiceString(m) && (j-i+1 > len(res)) {
res = s[i : j+1]
}
}
}
return res
}
func checkNiceString(m map[byte]int) bool {
for k := range m {
if k >= 97 && k <= 122 {
if _, ok := m[k-32]; !ok {
return false
}
}
if k >= 65 && k <= 90 {
if _, ok := m[k+32]; !ok {
return false
}
}
}
return true
}